This article is based on Tencent X5 kernel WebView practice summary, more complete than the previous article, specific.

OnPageFinished () callback timing

Analyze the timing of the onPageFinished() callback through the WebView callback function

The Android callback monitoring for loading a url is as follows:

    shouldOverrideUrlLoading   time: 1519274808392

    onPageStarted: time: 1519274808561 // 169ms

    onPageFinished   time: 1519274809735 // 1174ms
    onReadableCallback: false

    shouldOverrideUrlLoading   time: 1519274811067 --url :shanbay.native.app://document/ready
    onReadableCallback: true

    onPageFinished   time: 1519274817879 // 9318ms
    onReadableCallback: true
Copy the code

The first onPageFinished() callback is triggered at 1174ms (compared to onPageStarted()). The second onPageFinished() callback is triggered at 9318ms

Check the resource load sequence using Chrome ://inspect

The Network panel highlights two events: DOMContentLoaded and Load

DOMContentLoaded is triggered when the initial tag of the page is parsed. This event will display in two places on the Network panel:

  1. The blue vertical line in the Overview pane represents events.
  2. In the Summary pane, you can see the exact time of the event.

Load is triggered when the page is fully loaded. This event is displayed in three places:

  1. The red vertical line in the Overview pane represents events.
  2. The red bars in the Requests Table also represent events.
  3. In the Summary pane, you can see the exact time of the event.

Analyze the figure above:

  1. DOMContentLoadedloadEvent trigger timing andAndroidThe time when the callback is triggered is inconsistent.
  2. For the first time,onPageFinished()Method calls anddocumentType file is called after the file is loaded at a similar time and has been tested many times.
  3. The second timeonPageFinished()Method to call back time andloadClose in time.

Preliminary summary:

  1. For the first time,onPageFinished()Method is indocumentCalled after the type file is loaded.
  2. The second timeonPageFinished()Method is inloadCall back when done.
  3. By looking closely atshouldOverrideUrlLoadingandonPageStartedMethod time difference and figureOverviewBar, you will find that loading web pages is not the first time to request data. soonPageStarted()Methods have a certain delay time than triggers.

Ready replaces onPageFinished implementation

The onPageFinished() method is called multiple times, so if we put our business logic into this method, we will have some problems if we don’t control it. Of course, due to the diversity of web page types, problems can still occur on specific pages, even with controls.

So how do we get rid of rightonPageFinished()What about dependence?

The front-end will certainly have the perception of the life cycle of web page loading, so why don’t we rely on the front-end notification to trigger Native logic?

Through the above thinking, the event trigger of Native is completely left to the front end to retrieve actively, rather than through unreliable WebView callback. The $.ready() method on the front end tells the mobile to start executing the business logic.

And this way has a great improvement in timing performance over the second timeonPageFinished()Trigger much earlier (even more so on more complex pages)

A single page application

Above we optimized the business logic in the onPageFinished() method with active notification for Ready ().

However, in a single-page application, $.ready() fires only once on the home page, not on the child page, and the WebView’s shouldOverrideUrlLoading() and onPageStarted() methods do not call back. In some single-application pages the onPageFinished() method is triggered, and it requests a new resource, so we feel the callback. The onPageFinished() callback is not sensed by individual pages that replace the resource without asking for a new one.

Of course, if you develop your own pages, you don’t have to deal with these multiple cases, and you can negotiate a solution.

The main implementation of this paper is based on the third party web page to do function extension, so we need to consider these compatibility issues.

Give an immature reference scheme:

  1. The front endurlChange monitor notifies the mobile terminal of page changes.
  2. inonPageFinished()Method to do another bottom line operation, a loss of performance in exchange for user response speed.

Js injection timing and timing control

A common practice on the web is to inject Js scripts in onPageFinished().

There are some problems with this approach:

  • It may be injected multiple times.

  • OnPageFinished () is called a second time too late and suffers a significant performance penalty on complex pages.

  • If you inject too much, it will affect the experience of the page.

Since the number of script lines injected by the project is 1W+, we need to do some optimization on the timing. Make sure we’ve done the injection by the time we call.

Here we mainly inject to generate a script tag.

webView.loadUrl("javascript:(function() {" +
        "var scriptElement = document.getElementById('readability-script');" +
        "var parent = document.getElementsByTagName('body').item(0);" +
        "if(parent && ! scriptElement) {" +
        "var script = document.createElement('script');" +
        "script.type = 'text/javascript';" +
        "script.id = 'readability-script';" +
         // Tell the browser to BASE64-decode the string into your script !!!
        "script.innerHTML = window.atob('" + mAssetsScript + "');" +
        "parent.appendChild(script); }" +
        "}) ()");
Copy the code

Prevent multiple injections by controlling the uniqueness of labels; Complete the local JS script file reading before page initialization; Keep trying to inject until you can.

In the onProgressChanged() callback, repeated attempts are made to read the node injection script.

Through the initial analysis of onPageFinished(). Whether you can try to start the script injection on the first callback. However, there is no guarantee that onPageFinished() will be called back twice for every web page.

Normally, CSS does not block HTML parsing, but if it has JS behind it, it will block the execution of the JS until the CSS is loaded (even if the JS is an inline script), thus indirectly blocking HTML parsing.

Resource load callback

The resource loading callback onLoadResource() was discovered while studying the WebView loading sequence. Here’s a quick overview of what you can do with this callback.

Called when page resources are loaded, and once for each resource (such as an image) loaded.

webView.setWebViewClient(new WebViewClient(){
      @Override
      public boolean onLoadResource(WebView view, String url) {}});Copy the code

Pre-loading and manual caching can be realized. Optimize user experience and reduce traffic waste caused by multiple visits.

debugging

Create the most comfortable WebView debugging environment