Android

Key points of WebView static page loading solution in seconds

2025-10-29

//img.enjoy4fun.com/news_icon/d40suib8hlms72p24pt0.png

Applicable scenarios

1. Obtain the streaming output of the large model through the SSE interface and render it in real-time using WebView

Example of using evaluateJavaScript to update HTML content:

//img.enjoy4fun.com/news_icon/d40sl4h9q3nc72ve23e0.png

2. Multiple WebViews can be rendered simultaneously, supporting page switching similar to ViewPager2

The current plan can achieve:

1. WebView reuse saves time in creating WebViews

2. Avoid duplicate loading URLs to achieve data rendering in seconds


performance testing

Release+R8+Local HTML+Personal Machine

Type/TimeUntil creation completion (average)To start rendering (average)
No cache for the first time104ms230ms
No cache follow-up3ms64ms
cached0ms2ms


specific implementation

Cache Pool Implementation

  • Here, use host+path as the key and WebView as the value to build a WebView cache pool.
  • Use MutableContextWrapper to handle the situation where Context changes during reuse.

Minimalist WebViewCache.kt

//img.enjoy4fun.com/news_icon/d40spg38hlms72p1uiig.png

Specific usage

  • When using, determine whether to load the URL or directly call the JS method based on whether the URL is empty
  • If it is a newly created WebView, call it in the onPageFinished callback

JsWithCacheWebFragment.kt

//img.enjoy4fun.com/news_icon/d40sqb8vterc72pl6kog.png


Key issues and solutions

1. WebView creation time

The creation and related operations of WebViews must be done in the main thread, which is mandatory by Android. We can only create them in advance, put them in the cache pool, retrieve them from the cache pool when in use, and release them to the cache pool in a timely manner when not in use. There is currently no other way to optimize.

2. Loading URL takes time

In fact, the initial creation process may take longer, while the loadURL is consistently slower. Testing local HTML files takes about 50ms at the fastest, so avoiding calling this method is the key to optimizing time consumption.

3. onPageFinished callback multiple times

The internal mechanism of Android Webview determines it, which can be determined by using WebView. progress==100

4. Enter the page but the cache pool is empty

Without preheating in advance, the creation of WebViews and laodURLs cannot be avoided during the first use, and can only be loaded in advance.

Preloading requires determining the appropriate timing, which is generally recommended to be done through idleHeader.

//img.enjoy4fun.com/news_icon/d40sqnr8hlms72p208ig.png

Then call at the appropriate time

Looper.getMainLooper().queue.addIdleHandler(WebViewCache.preloadIdleHandler)

5. Memory leakage

Mainly the context and WebViewClient, we can reset them when releasing.

7. Memory usage may be too high

Mainly related to the content of the rendered page, WebView itself does not actually occupy a lot of memory, and multiple instances will not cause a linear increase in memory usage.

You can reduce memory by optimizing code logic and adjusting cache pool size.

8. Possible Faster WEB Communication Methods

I have always heard that WebMessagePort performs better than JSInterface, but I did not see any performance difference in this minimalist scenario on the demo. Perhaps the interaction frequency is still not enough. ChatGPT says it is suitable for transmitting audio and video streams.


Key issues and solutions in the demo effect of ViewPager2+BottomSheet

1. Implement nested sliding to solve the problem of possible inability to slide

ViewPager2 is actually implemented using RecyclerView internally, and its nested sliding needs to be disabled first. Then, because the content page needs to be linked with BottomSheet, NestdScrollView needs to be used.

//img.enjoy4fun.com/news_icon/d40ss719q3nc72vebm70.png

Additionally, there may be a situation where nested sliding is not possible after switching tabs, which is a known issue with BottomSheet and is detailed in this analysis article. However, this problem was not encountered in the demo.

2. How to achieve preloading of the next page with up to three tabs simultaneously

I strongly recommend reading this ViewPager2 analysis article. Simply put:

  • Offscreen PageLimit=1 to achieve preloading of the next page
  • IsItemPrefetcheEnabled=false+setItemViewCacheSize (0) implements up to three tabs simultaneously

3. Click on the serial number to quickly switch between tab lagging

Because ViewPager2 uses RecyclerView internally, and the default for quick switching is SmoothScrollTo, this may cause tabs passing by along the way to be quickly loaded and then quickly destroyed. When the logic becomes complex, rebuilding and destroying five or six tabs at the same time will naturally deteriorate the performance.

To avoid this issue while also supporting left and right switching, you can:

Determine whether it is scrollTo or smoothscrollTo by checking the distance between the current position and the target position when clicking

When clicked, scroll directly to

4. The default BottomSheetDialog's BottomSheet will not be full screen

The BottomSheetBehavior of BottomSheetDialog is added to the FrameLayout, and its default measurement behavior is to determine its own height based on the maximum value of childView, and it will ignore the highMeasureSpec passed from the upper layer.

So in the demo, we customized the onMeasure method for FrameLayout, fixed the height to the maximum value, and then stuffed ViewPager2 into this FrameLayout.

more stories
See more