安卓WebView性能

19
еңЁжҲ‘зҡ„еә”з”ЁзЁӢеәҸдёӯпјҢжҲ‘жӯЈеңЁдҪҝз”ЁWebViewеҠ иҪҪдёҖзі»еҲ—еӨ–йғЁURLпјҢ并е…Ғи®ёз”ЁжҲ·йҖҡиҝҮе®ғ们иҝӣиЎҢзҝ»йЎөгҖӮ WebViewеҠ иҪҪеңЁViewFlipperдёҠгҖӮ жҲ‘еҸ‘зҺ°WebViewеҠ иҪҪURLзҡ„жҖ§иғҪйқһеёёе·®гҖӮ жҲ‘е°қиҜ•иҝҮдҪҝз”ЁFrameLayoutпјҢйҷҗеҲ¶еҠ иҪҪзҡ„WebViewж•°йҮҸзӯүжүҖжңүж–№жі•пјҢдҪҶжҖ§иғҪд»Қ然дёҚзҗҶжғігҖӮ
еҰӮдҪ•дјҳеҢ–WebViewзҡ„жҖ§иғҪпјҹиҝҷеә”иҜҘжҳҜдёҖдёӘеёёи§Ғзҡ„з”Ёжі•гҖӮжҲ‘жҳҜеҗҰеҝҪз•ҘдәҶжҳҺжҳҫзҡ„й—®йўҳпјҹ
жҲ‘зҡ„WebViewи®ҫзҪ®дёә -
    webView.setInitialScale(WEBVIEW_SCALE);
    webView.getSettings().setJavaScriptEnabled(true);
    webView.getSettings().setBuiltInZoomControls(false);
    webView.setWebViewClient(new MyWebViewClient());    
    webView.setOnTouchListener( new OnTouchListener());

你确定问题不是因为无法从互联网加载数据吗? - Falmarri
不行,数据已经加载了。但是需要很长时间。 - Usha
1
一次加载多个页面非常耗费资源 - 即使是单个网页的加载也是很昂贵的操作。暂时放置所有像图片处理、视口缩放等处理方面的问题不谈,还有许多并发套接字连接的性能限制。最后我猜想,如果你观察日志,你会看到很多GC thrash。同时激活多个WebView并不是一个明智的选择。如果没有“性能不佳”的定量描述或者你运行的手机型号信息,我只能猜测你无法做太多来改善它。 - cistearns
我花了不少时间尝试优化同样的想法,并发现这并不是一个好的解决方案。在页面加载和视图翻转之间存在着太多的开销。在我的情况下,我能够通过将每个页面加载到按CSS3列排序的一个大页面中,并使用fling在列之间切换来获得可以接受的性能。当一个大页面被渲染时仍然会有延迟,但比将每个页面加载到viewflipper中快几倍。然而,这对于复杂的HTML文档来说并不适用...我的文档只包含文本和一些图像。 - Turnsole
4个回答

4

试试这个:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    webView.setLayerType(View.LAYER_TYPE_HARDWARE, null); 
} else {
    webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

3
我认为以下方法最好:
if (Build.VERSION.SDK_INT >= 19) {
    webView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
}       
else {
    webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

Android 19使用Chromium引擎作为WebView内核。我猜它在硬件加速方面表现更佳。

欲了解更多信息,请参阅Android 4.4 KitKat,浏览器和Chrome WebView


2

这个问题已经在这里讨论过了:Enhance webView performance (should be the same performance as native Web Browser)

我遇到了类似的问题,经过一番重度调试后发现本地浏览器和WebView浏览器似乎使用不同的缓存。

这段代码可以用于禁用WebView缓存,并使WebView更快(尽管代价是不缓存)。请注意,它使用了私有API,因此使用它会冒着代码在未来版本中无法使用的风险:

try
{
  Method m = CacheManager.class.getDeclaredMethod("setCacheDisabled", boolean.class);
  m.setAccessible(true);
  m.invoke(null, true);
}
catch (Throwable e)
{
  Log.i("myapp","Reflection failed", e);
}

这样会禁用应用程序使用的每个 WebView 的缓存吗?有没有办法仅禁用单个 WebView 的缓存?谢谢! - Sven Viking
看起来我的问题可能可以通过WebSettings方法 .setCacheMode(WebSettings.LOAD_NO_CACHE); 得到解答。 - Sven Viking
虽然根据这个问题,它要么不起作用,要么只是跳过缓存检查但仍保存到缓存。https://dev59.com/sm435IYBdhLWcg3wvyw5 - Sven Viking
4
我认为这个设置是针对页面的第二次加载。我从setCacheMode的API中得到了这个信息:缓存的使用方式基于导航选项。对于普通页面加载,会检查缓存并根据需要重新验证内容。当返回时,不会重新验证内容,而是直接从缓存中取出内容。这个函数允许客户端覆盖此行为。 - Ashok Goli
1
我在setCacheDisabled方法上遇到了一个java.lang.NoSuchMethodException异常。也许这个方法已经被标记为废弃并移除了? - DBX12
禁用缓存是一种欺骗行为。 - Josh

0

改进的答案: 上述解决方案提到的CacheManager.class不受支持。

 try {
            val m: Method = ServiceWorkerWebSettingsCompat.CacheMode::class.java.getDeclaredMethod(
                "setCacheDisabled",
                Boolean::class.javaPrimitiveType
            )
            m.isAccessible = true
            m.invoke(null, true)
        } catch (e: Throwable) {
            Log.i("myapp", "Reflection failed", e)
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接