23

我正在开发一个名为 Lightning Browser 的开源浏览器,但在最近更新到 Android (4.2.2) 时遇到了一些问题。

在触摸视图之前,WebView 将无法完全呈现。它仅发生在最新的 Android 版本上。在 4.2.1 上,WebView 渲染得非常好。我使用 Nexus 7 进行开发,在收到 4.2.2 更新后,浏览器立即停止渲染。其他用户也遇到过这种情况,并且多次确认仅在 4.2.2 上发生。它正在针对 API 级别 16 和 17 发生,但我已经看到针对 API 级别 9 的 WebKit 浏览器没有这个问题。

我试图使用我在 Stack Overflow 上找到的问题的解决方案来解决这个问题(Android WebView 呈现空白/白色,视图不会在 css 更改或 HTML 更改时更新,动画不连贯)。但是,仅将 WebView 的 RenderPriority 设置为高并不能解决它......让它在不被触摸的情况下呈现的唯一方法是将 invalidate() 命令放在 WebView 的 OnDraw() 方法中。这会导致 WebView 不断地重新绘制。这可行(有点),动画很流畅,页面加载非常快,但否则会导致 WebView 的性能下降。

我也看过这个问题(与我的非常相似),但没有很好的答案。在用户交互之前,Android WebView 无法完全呈现内容

性能下降,我的意思是输入。文本输入滞后,WebView 本身无法像以前那样处理正在发生的事情。使用 invalidate() 方法调用对浏览器进行基准测试会使基准测试性能下降约 8%。我知道基准测试并不是万能的,但它告诉我连续绘图正在使系统紧张并导致系统忽略其他任务。

结论... Android 4.2.2 中的 WebView 在触摸之前不会呈现。我知道解决此问题的唯一方法是在 WebView 的 onDraw() 方法中调用 invalidate()。这对性能不利,我正在寻找一种不同的方法来解决这个问题。

魔法密码(我目前正在使用)...

class MyWebView extends WebView
{
    @Override
    onDraw(Canvas canvas)
    {
        invalidate(); 
        super.OnDraw(canvas);
    }
}

消除

invalidate();

并且在触摸之前它不会渲染。

有没有人对如何使 WebView 渲染有建议(除了我所做的)?顺便说一句,这是我在 Stack 上提出的第一个问题,如果我不清楚或者我做错了什么,请原谅我。

编辑:我在这里发现了这个关于类似问题的问题,并且已经解决,问题是,我什至不明白答案的含义。如果有人能启发我,它可能会有所帮助。

我在 logcat 中收到此错误

E/chromium(1243): external/chromium/net/disk_cache/backend_impl.cc:2022: [0705/172030:ERROR:backend_impl.cc(2022)] Corrupt Index file
4

4 回答 4

9

所以我终于找到了导致 WebView 不呈现的问题。我正在我的 WebView 的 WebViewClient 内启动和停止可绘制的动画。这个drawable只是一个在页面加载时旋转的刷新按钮......简单吧?

那么在浏览器的非全屏模式下,旋转drawable和WebView都是同一个父级的子级,而在全屏模式下,drawable成为WebView的子级。不知何故,通过在页面加载时启动动画并在完成时(全屏)停止动画,应用程序决定旋转可绘制对象需要所有绘图能力,而 WebView 从不绘制。当处于全屏模式并且可绘制对象成为 WebView 的子对象时,WebView 的渲染优先级高于可绘制对象,并且可以正常绘制。

这个故事的寓意是...... WebViews 喜欢成为要绘制的最高优先级视图。如果有其他视图获得更高的优先级,它们将无法正确绘制。

我不是动画方面的专家,所以我现在需要重新考虑如何为可绘制对象设置动画,以免中断 WebView。

希望这是有道理的。谢谢阅读。

于 2013-03-29T17:08:36.860 回答
4

在清单上禁用硬件加速:

安卓:硬件加速=“假”

于 2013-05-24T07:19:00.040 回答
2

请参阅@Olivier 在Android 上的最后一个答案 WebView 呈现空白/白色,视图不会在 css 更改或 HTML 更改时更新,动画不连贯,他在 WebView 的 OnTouchEvent 上触发了几个延迟失效,而不是在 onDraw 上连续触发 ...我的情况很有效,因为(大多数)我的问题是在用户触摸 webview 之后我更改了一些 CSS 作为响应。当然,它根本不适用于自动/超时 css 的情况

在我的例子中,它还有助于从 Java 导出一个 JavaScript 函数来手动触发延迟失效,所以如果在 JavaScript 中你或多或少知道灾难可能发生在哪里,你可以手动触发它,就像你的 WebView 中的这个内部类一样:

public class MyWebView extends WebView {

    private class InvalidateExtension {

        private Handler handler=new Handler(); // you might already have a handler
        private Runnable mInvalidater=new Runnable() {

            @Override
            public void run() {
                MyWebView.this.invalidate();
            }

        }

        public void trigger(int delay) {
                handler.postDelayed(mInvalidater, delay);
                handler.postDelayed(mInvalidater, 2*delay); // just in case
                handler.postDelayed(mInvalidater, 4*delay); // just in case just in case :)
        }
    }


    /** Call this function on this view's init, BEFORE loading a page so it is available to JS */
    private void call_me_on_init_to_enable_hack() {
        addJavascriptInterface(new InvalidateExtension(), "Invalidater");
    }
}

因此,您可以从 JavaScript 执行以下操作:

Invalidater.trigger(100);

并使用毫秒值....

希望这对某人有帮助!

于 2013-05-09T23:11:42.617 回答
2

旋转手机时缩放比例有问题,会导致此问题,部分或整个页面将无法绘制。要在您的 WebViewClient 实现中解决此覆盖 onScaleChanged 并使视图无效。这应该在需要时强制重绘。

@Override
    public void onScaleChanged(WebView view, float oldScale, float newScale) {
        if (view != null) {
            view.invalidate();
        }
    }
于 2013-06-26T09:56:22.773 回答