標籤:

理解Android中WebView相關的幾個概念

學知識就是要掌握一些概念的內涵和外延。So,讓我們看看與WebView相關的幾個概念吧。

  • WebView:一個絕對布局容器,用來展示或渲染Web頁面。
  • WebSettings:一個抽象類,包含對WebView的設置方法。用來對WebView進行設置,比如支持JS、緩存模式等。
  • WebViewClient:這個類的方法有一個特點,就是參數的第一項就是WebView,其他項是事件或數據信息。WebView通過該類對外通知頁面載入相關的消息用來在頁面載入的各個階段進行業務處理,處理載入錯誤情況,攔截頁面內和頁面外的請求。
  • WebChromeClientWebView:WebView通過該類,通知獲取到站點圖標、標題、載入進度,以及JS對話框等,用來更好地展示頁面和交互。

理解了上面幾個概念後,我們就可以處理一般的業務需求了。比如

設置緩存

緩存模式

獲取到WebSettings然後調用其中的設置方法就可以了。

WebSettings webSettings = webView.getSettings();nwebSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);n

緩存模式有LOAD_DEFAULT(默認)、LOAD_CACHE_ELSE_NETWORK(先緩存後網路)、LOAD_NO_CACHE(不要緩存)、LOAD_CACHE_ONLY(只要緩存),可以根據業務要求選擇。

緩存機制

(1)瀏覽器緩存機制

  • 概念:通過 HTTP 協議頭裡的 Cache-Control(或 Expires)和 Last-Modified(或 Etag)等欄位來控制文件緩存的機制。

  • 適用:適用於 Web 的靜態資源文件。

(2)Dom Storage(Web Storage)

  • 概念:通過存儲字元串的 Key/Value 對來提供,並提供 5MB (不同瀏覽器可能不同,分 HOST)的存儲空間(Cookies 才 4KB)。分為 sessionStorage 和 localStorage。

  • 適用:代替掉將一些不需要讓伺服器知道的信息存儲到 cookies 里的這種傳統方法。webSettings.setDomStorageEnabled(true);

(3)Web SQL Database

  • 概念:基於 SQL 的資料庫存儲機制,用於存儲適合資料庫的結構化數據。

  • 適用:Web SQL Database 存儲機制不再推薦使用,將來也不再維護,而是推薦使用 AppCache 和 IndexedDB。

webSettings.setDatabaseEnabled(true);nfinal String dbPath = getApplicationContext().getDir("db", Context.MODE_PRIVATE).getPath();nwebSettings.setDatabasePath(dbPath);n

(4)Application Cache(AppCache)

  • 概念:為支持 Web App 離線使用而開發的緩存機制。以文件為單位進行緩存,且文件有一定更新機制。

  • 適用:AppCache 是對瀏覽器緩存機制的補充,不是替代。不推薦使用了,標準也不會再支持。

webSettings.setAppCacheEnabled(true);nfinal String cachePath = getApplicationContext().getDir("cache", Context.MODE_PRIVATE).getPath();nwebSettings.setAppCachePath(cachePath);nwebSettings.setAppCacheMaxSize(5*1024*1024);n

(5)Indexed Database

  • 概念:NoSQL 資料庫,類似於 Dom Storage 的 key-value 的存儲方式,但功能更強大,且存儲空間更大。

  • 適用:用於存儲大塊或複雜結構的數據,提供更大的存儲空間,使用起來也比較簡單。可以作為 Web SQL Database 的替代。不太適合靜態文件的緩存。webSettings.setJavaScriptEnabled(true);

(6)File System API

  • 概念:為 Web App 提供了一個虛擬的文件系統,運行在沙盒中

  • 適用:任何需要通過文件來管理數據,或通過文件系統進行數據管理的場景都比較適合。到目前,Android 系統的 Webview 還不支持 File System API。

處理頁面導航

方法一

@Overridenpublic boolean onKeyDown(int keyCode, KeyEvent event) {n if ((keyCode == KeyEvent.KEYCODE_BACK) && myWebView.canGoBack()) {n myWebView.goBack();n return true;n }n return super.onKeyDown(keyCode, event);n}n

方法二

@Overridenpublic void onBackPressed() {n if (webView.canGoBack()) {n webView.goBack();n } else {n super.onBackPressed();n }n}n

與Activity/Fragment生命周期相適應

參考WebViewFragment實現

/**n * A fragment that displays a WebView.n * <p>n * The WebView is automically paused or resumed when the Fragment is paused or resumed.n */npublic class WebViewFragment extends Fragment {n private WebView mWebView;n private boolean mIsWebViewAvailable;nn public WebViewFragment() {n }nn /**n * Called to instantiate the view. Creates and returns the WebView.n */n @Overriden public View onCreateView(LayoutInflater inflater, ViewGroup container,n Bundle savedInstanceState) {n if (mWebView != null) {n mWebView.destroy();n }n mWebView = new WebView(getActivity());n mIsWebViewAvailable = true;n return mWebView;n }nn /**n * Called when the fragment is visible to the user and actively running. Resumes the WebView.n */n @Overriden public void onPause() {n super.onPause();n mWebView.onPause();n }nn /**n * Called when the fragment is no longer resumed. Pauses the WebView.n */n @Overriden public void onResume() {n mWebView.onResume();n super.onResume();n }nn /**n * Called when the WebView has been detached from the fragment.n * The WebView is no longer available after this time.n */n @Overriden public void onDestroyView() {n mIsWebViewAvailable = false;n super.onDestroyView();n }nn /**n * Called when the fragment is no longer in use. Destroys the internal state of the WebView.n */n @Overriden public void onDestroy() {n if (mWebView != null) {n mWebView.destroy();n mWebView = null;n }n super.onDestroy();n }nn /**n * Gets the WebView.n */n public WebView getWebView() {n return mIsWebViewAvailable ? mWebView : null;n }n}n

展示頁面載入進度

舊有的實現

參考Android: The progress bar in the window』s title does not display文中的一種實現,然而看了下發布時間是2010.06。注意:那時候用的是Android 2.3,BrowserActivity不是繼承自AppCompactActivity,使用的主題也不是AppCompact主題。

public void onCreate(Bundle savedInstanceState) {n super.onCreate(savedInstanceState);n requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);n requestWindowFeature(Window.FEATURE_PROGRESS);n currentURL = BrowserActivity.this.getIntent().getExtras().getString("currentURL");nn setContentView(R.layout.browser);nn setProgressBarIndeterminateVisibility(true);n setProgressBarVisibility(true);nn try {n mWebView = (WebView) findViewById(R.id.webview);n mWebView.getSettings().setJavaScriptEnabled(true);n mWebView.setWebViewClient(new browserActivityClient());nn mWebView.setWebChromeClient(new WebChromeClient() {n public void onProgressChanged(WebView view, int progress) {n setProgress(progress * 100);n if(progress == 100) {n setProgressBarIndeterminateVisibility(false);n setProgressBarVisibility(false);n }n }n });n mWebView.loadUrl(currentURL);n } catch (Exception e) {n Log.e(getClass().getSimpleName(), "Browser: " + e.getMessage());n Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();n } n}n

自定義實現

  • 思路:在webView內部或外部添加一個ProgressBar(水平樣式),並通過WebChromeClient獲知頁面的載入進度,進而調整ProgressBar的進度。

  • 實現:

    WebChromeClient webChromeClient = new WebChromeClient() {n @Overriden public void onProgressChanged(WebView view, int newProgress) {n if (newProgress == 100) {n progressBar.setVisibility(View.GONE);n } else {n progressBar.setVisibility(View.VISIBLE);n progressBar.setProgress(newProgress);n }n }n};nwebView.setWebViewClient(webViewClient);n

參考文檔

  1. H5 緩存機制淺析 移動端 Web 載入性能優化

推薦閱讀:

H5 和移動端 WebView 緩存機制解析與實戰

TAG:webview | Android |