【问题标题】:Android WebView performanceAndroid WebView 性能
【发布时间】:2023-03-24 15:23:01
【问题描述】:

在我的应用程序中,我正在 webview 中加载外部 url 列表并允许用户翻阅它们。 Webview 被加载到视图翻转器上。我发现 webview 加载 url 的性能真的很差。我已经尝试了从使用框架布局到限制要加载的 webview 数量的所有方法。性能还是不尽如人意。

如何优化 webview 的性能?这应该是一种常见的用法。我是否遗漏了一些明显的东西。

我的 Webview 设置是 -

    webView.setInitialScale(WEBVIEW_SCALE);
    webView.getSettings().setJavaScriptEnabled(true);
    webView.getSettings().setBuiltInZoomControls(false);
    webView.setWebViewClient(new MyWebViewClient());    
    webView.setOnTouchListener( new OnTouchListener());

【问题讨论】:

  • 你确定不是从互联网加载数据的问题吗?
  • 不。数据已加载。但这需要很长时间。
  • 一次加载多个页面的成本很高——即使加载一个网页也是一项昂贵的操作。抛开图像处理、视口缩放等所有事情不谈。许多并发套接字连接的性能也存在限制。最后我猜如果你看日志你会看到很多 GC thrash。一次激活多个 WebView 并不可取。如果没有对“性能不令人满意”或您正在运行的手机进行定量描述,我只能猜测您无能为力。
  • 我花了相当多的时间尝试优化同一种想法,发现它确实不是一个好的解决方案。页面加载和 viewflipper 之间的开销太大了。就我而言,通过将每个页面加载到按 CSS3 列排序的页面中,并使用 fling 在列之间移动,我能够获得良好的性能。渲染一个大页面时仍然存在延迟,但它比将每个页面加载到 viewflipper 中要快几倍。不过,这确实不适用于复杂的 html 文档……我的只有文本和几张图片。

标签: android webview


【解决方案1】:

试试这个:

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

【讨论】:

    【解决方案2】:

    我认为以下方法效果最好:

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

    Android 19 具有用于 WebView 的 Chromium 引擎。我想它在硬件加速方面效果更好。

    欲了解更多信息Android 4.4 KitKat, the browser and the Chrome WebView

    【讨论】:

      【解决方案3】:

      这里已经讨论过了: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 的缓存?谢谢!
      • 看来我的问题可以通过WebSettings方法.setCacheMode(WebSettings.LOAD_NO_CACHE);来回答
      • 虽然根据这个问题,它要么不起作用,要么只跳过缓存检查但仍然保存到缓存中。 stackoverflow.com/questions/5239954/…
      • 我认为这个设置是为了页面的第二次加载。我从 setCacheMode 的 api 中得到了这个:缓存的使用方式基于导航选项。对于正常的页面加载,会检查缓存并根据需要重新验证内容。向后导航时,不会重新验证内容,而是从缓存中提取内容。此函数允许客户端覆盖此行为。
      • 我得到了java.lang.NoSuchMethodExceptionsetCacheDisabled。也许这个功能已被弃用和删除?
      【解决方案4】:

      即兴回答: 上面提到的 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)
              }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-25
        • 1970-01-01
        • 1970-01-01
        • 2012-06-01
        • 2018-08-12
        相关资源
        最近更新 更多