WebView related concepts

The background,

To learn something, first of all, you should know why to learn it, and then some ways to use it. So why use a WebView? We know that apps like e-commerce often have some activities, if the use of native Android development, both time and energy consumption, App updates frequently. But with a WebView, you only need to change the HTML page, saving a lot of money.

Second, the introduction of

WebView is a webKit-based control that presents web pages.

WebView does the following:

  • Display and render Web pages in the App.
  • Use HTML directly for layout.
  • You can interact with JS.

WebView usage details

WebView can be used by itself or in conjunction with its utility classes. The following three main parts are introduced:

  • Common methods of WebView itself.
  • WebView utility class: WebSettings, WebViewClient, WebChromeClient.
  • Interaction between Android and JS.

First, WebView itself common methods

  • Load the URL

    // Load from web page
    webview.loadUrl("https://google.com")
    // Load the HTML under apk
    webview.loadUrl("file://android_asset/test.html")
    // Load the phone's local HTML
    webview.loadUrl("content://com.android.htmlfileprovider/sdcard/test.html")
    Copy the code
  • The state of the WebView

    // Activate the WebView state to execute web page responses
    webview.onResume()
    // The loss of focus is not visible, telling the kernel to suspend all action
    webview.onPause()
    // Suspend all WebView actions to reduce consumption
    webview.pauseTimer()
    // Resume action
    webview.resumeTimers()
    Copy the code
  • About forward/back pages

    // Can I back up
    Webview.canGoBack() 
    // Back up the page
    Webview.goBack()
    
    // Whether can advance
    Webview.canGoForward()
    // Forward the page
    Webview.goForward()
    
    // Use the current index as the starting point to move forward or backward to the steps specified in the history
    // If steps is negative, steps are backward, and positive steps are forward
    Webview.goBackOrForward(intsteps) 
    Copy the code
  • Resolve the Back key Finish Browser

    // Pressing the phone's back will finish() itself, and the following code fixes this problem
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if ((keyCode == KEYCODE_BACK) && mWebView.canGoBack()) { 
            mWebView.goBack();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }
    Copy the code

Second, WebView combined use of the tool class

1, the WebSettings class

  • Two ways to create a WebView

    // 1. Generate it directly in the Activity
    WebView webview = new WebView(this)
    // 2. Define in the XML layout and get the object in the Activity
    WebView webview = findViewById(R.id.webview)
    Copy the code
  • Use WebSettings for configuration

    // Declare a WebSettings subclass
    WebSettings webSettings = webView.getSettings();
    
    // The WebView must be set up to support Javascript if the page to be accessed interacts with Javascript
    webSettings.setJavaScriptEnabled(true);  
    // If the HTML is loaded and JS is performing animation and other operations, it will cause resource waste (CPU, battery).
    // Set setJavaScriptEnabled() to false in onStop and true in onResume
    
    // Support plugins
    webSettings.setPluginsEnabled(true); 
    
    // Set up the adaptive screen
    webSettings.setUseWideViewPort(true); // Resize the image to fit the WebView
    webSettings.setLoadWithOverviewMode(true); // Zoom to the size of the screen
    
    // Zoom
    webSettings.setSupportZoom(true); // Supports scaling and defaults to true. That's the premise of the following one.
    webSettings.setBuiltInZoomControls(true); // Set the built-in zoom control. If false, the WebView is not scalable
    webSettings.setDisplayZoomControls(false); // Hide the native zoom control
    
    // Other details
    // As long as there is local data, whether expired or no-cache, use the data in the cache
    webSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);  
    // Do not use cache, only get data from network
    webSettings.setCacheMode(WebSettings.LOAD_NO_CACHE);
    // (default) Cache-control or last-Modified determines whether to fetch data from the network
    webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
    // Do not use network, only read local cache data
    webSettings.setCacheMode(WebSettings.LOAD_CACHE_ONLY);
    webSettings.setAllowFileAccess(true); // Set access to files
    webSettings.setJavaScriptCanOpenWindowsAutomatically(true); // Support to open new Windows through JS
    webSettings.setLoadsImagesAutomatically(true); // Support automatic loading of images
    webSettings.setDefaultTextEncodingName("utf-8");// Set the encoding format
    Copy the code

2, the WebViewClient class

  • Function: Handles notification & request events

  • Common methods:

    webview.setWebViewClient(new WebViewClient(){
    	@Override
    	public boolean shouldOverrideUrlLoading(View view,String url){ view.loadUrl(url); }});// To open a web page, the browser is not called, but directly displayed in the WebView
    shouldOverrideUrlLoading()
    // called when the page starts loading
    onPageStarted()
    // called when the page is finished loading
    onPageFinish()
    // called when the page loads resources, once for each resource
    onLoadResource()
    // Called when an error occurs on the server loading the page
    onReceivedError()
    Copy the code

3, WebChromeClient class

  • Function: assist WebView to handle JS dialog box, website icon, website title, etc.

  • Common methods:

    // Get the loading progress of the page and display it
    onProgressChanged()
    // Get the Web page title
    onReceivedTitle()
    // Support the JS warning box
    onJsAlter()
    / /...
    Copy the code

WebView and JavaScript interaction

  • Android calls JS code summary
    • LoadUrl () via WebView.
    • EvaluateJavaScript () via WebView.
  • JS call Android code summary
    • Object mapping is done by calling WebView’s addJavascriptInterface().
    • Intercepting JS dialogs alter(), confirm(), prompt() via WebViewClient onJsAlter(), onJsConfirm(), onJsPrompt()

3. WebView memory leakage problem

1. How to avoid memory leaks

  • Instead of defining webViews in XML, they are created in the Activity when needed, and the Context uses getApplicationContext().

    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
            mWebView = new WebView(getApplicationContext());
            mWebView.setLayoutParams(params);
            mLayout.addView(mWebView);
    Copy the code
  • When the Activity is destroyed, let the WebView load null, then remove the WebView, and finally empty it.

    @Override
        protected void onDestroy(a) {
            if(mWebView ! =null) {
              	// Load null content first
                mWebView.loadDataWithBaseURL(null.""."text/html"."utf-8".null);
                mWebView.clearHistory();
    						/ / remove the WebView
                ((ViewGroup) mWebView.getParent()).removeView(mWebView);
              	/ / destroy
                mWebView.destroy();
              	/ / empty
                mWebView = null;
            }
            super.onDestroy();
        }
    Copy the code

2. Explore the cause of memory leaks (TODO)

This is caused by the WebView kernel and usually occurs on earlier versions of Android, which have been fixed. The reasons are as follows:

Org.chromium.android_webview. AwContents class registered component Callbacks, but did not unregister properly. Org.chromium.android_webview. AwContents has these two methods onAttachedToWindow and onDetachedFromWindow; The system registers and unregisters component callback on attach and Detach

Related articles: juejin.cn/post/690148…

4. Webview-related performance optimization

The impression of WebView is that its loading speed is very slow, much slower than Native, and it often takes a lot of time to load a page. This requires us to optimize the WebView. First of all, we need to understand the startup process of WebView:

1. WebView initialization

What can be done to solve the problem of loading resources for a page only after the WebView has been created and initialized? There are several common solutions:

  • Get the global Context

    Reduces the WebView initialization time when the App is first opened, but increases the additional memory consumption. At the same time, skipping between pages requires clearing the traces of the previous page, which is more likely to cause memory leaks.

  • Client proxy data request

    • When the client initializes the WebView, the network requests data directly from Native.
    • When the page is initialized, the data requested by its agent is fetched from Native.

    This approach does not reduce WebView initialization time, but data requests and WebView initialization occur simultaneously, resulting in a shorter overall page load time.

2. Establish the connection/server processing

  • DNS uses the same domain name as the client API

    When the WebView is opened for the first time, the client will initiate a request for a domain name, and its DNS will be cached. When the WebView is opened, the client will make a request for a new Api, and the DNS request will be initiated again, increasing the consumption of time.

  • Synchronous rendering is chunk encoded

    If synchronous rendering takes too long, consider using chunk encoding, putting data last and loading static content first. For the traditional post-rendering, the loading mode of [browser] -> [Web API] -> [business API] is often adopted, and the post-rendering time refers to the processing time of [Web API]. Web apis here generally serve two purposes:

    • Determine the version of the static resource.
    • According to the user’s request, go to the business API to get data.

    Versioning static resources is essentially time – free, and back-end request time is spent on business API requests. So how do you optimize this time? We can set transfer-encoding:chunked in the header so that the page can be output in chunks. If we design the page properly so that the head part is the content related to certain static resource version and the body part is the content related to business data, then we can make the user request, Output the parts of the Web API that can be determined to the browser first, and then transfer the API data to the browser when the API is fully retrieved. The following figure shows the difference between a chunk request and a full output:

3. Page frame rendering

In general, the front-end CSS loading and javascript script execution will not block the page parsing, but if both appear in the wrong order, it will block the page parsing.

  • CSS does not prevent the page from being parsed down.
  • The inline JS executes quickly and continues parsing the document.
  • But loading CSS blocks subsequent JS execution, which indirectly blocks HTML parsing.

Reference article:

www.jianshu.com/p/3c94ae673…

www.jianshu.com/p/345f4d8a5…

www.jianshu.com/p/3e8f7dbb0…

Juejin. Cn/post / 690148…