WebView在Android 4.2.2之前无法渲染

WebView在Android 4.2.2之前无法渲染,android,android-webview,Android,Android Webview,我正在开发一款名为Lightning browser的开源浏览器,在Android的最新更新(4.2.2)中遇到了一些问题 在触摸视图之前,WebView将无法完全渲染。它只出现在最新的Android版本上。在4.2.1中,WebView呈现得非常好。我使用Nexus7进行开发,在收到4.2.2更新后,浏览器立即停止渲染。其他用户也经历过这种情况,并多次确认仅在4.2.2上发生。它的目标是API级别16和17,但我已经看到一个WebKit浏览器,它的目标是API级别9,而没有这个问题 我尝试使用

我正在开发一款名为Lightning browser的开源浏览器,在Android的最新更新(4.2.2)中遇到了一些问题

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

我尝试使用我在这里发现的堆栈溢出()问题的解决方案来解决这个问题。但是,仅将WebView的RenderPriority设置为high并不能解决此问题。。。要使其在不被触摸的情况下进行渲染,唯一的方法是将invalidate()命令放在WebView的OnDraw()方法中。这会导致WebView连续重新绘制。这可以工作(某种程度上),动画是平滑的,页面加载非常快,但它会导致WebView的性能下降

我也看到过这个问题(与我的问题非常相似),但没有很好的答案

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

总之。。。 Android 4.2.2中的WebView在触摸之前不会渲染。我知道解决这个问题的唯一方法是在WebView的onDraw()方法中调用invalidate()。这对性能不好,我正在寻找一种不同的方法来解决这个问题

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

除去

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

因此,我最终发现了导致WebView无法渲染的问题。我正在启动和停止WebView的WebViewClient中可绘制的动画。这个可绘制的只是一个刷新按钮,当页面加载时它会旋转。。。简单对吧

在浏览器的非全屏模式下,旋转可绘制和WebView都是同一父对象的子对象,而在全屏模式下,可绘制成为WebView的子对象。不知何故,通过在页面加载时启动动画并在加载完成时停止动画(全屏),应用程序决定旋转可绘制文件需要所有绘图功能,而WebView永远不会绘制。当处于全屏模式且可绘制文件成为WebView的子文件时,WebView的渲染优先级高于可绘制文件,并且绘制效果良好

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

我不是动画方面的专家,所以我需要重新思考我现在是如何制作可绘制动画的,这样就不会中断网络视图


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

请看@Olivier on的最后一个答案,他在WebView的OnTouchEvent上触发了几次延迟失效,而不是在onDraw上继续。。。在我的例子中,它起作用了,因为(大多数)我的问题是在用户触摸webview之后,我改变了一些CSS作为回应。当然,它根本不适用于自动/超时css

在我的例子中,它还帮助从Java导出JavaScript函数以延迟手动触发invalidate,因此,如果在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);
并播放毫秒值


希望这对别人有帮助

禁用清单上的硬件加速:


android:hardwareAccelerated=“false”

旋转手机时缩放比例出现问题,这将导致此问题,部分或整个页面将无法绘制。要解决此覆盖问题,请在WebViewClient实现中更改并使视图无效。这将在需要时强制重新绘制

@Override
    public void onScaleChanged(WebView view, float oldScale, float newScale) {
        if (view != null) {
            view.invalidate();
        }
    }

说到动画,我已经看到,如果你在页面的某个地方应用一个虚拟HTML动画,它将触发webview重画。。。但这是一个非常肮脏的黑客…天哪。那正是我在做的!我被困了好几天,为什么抽绳不能加载。谢谢。所以答案是不使用旋转动画?但这不会发生在运行Android Kitkat的设备上。他们解决了什么问题吗?这个问题与我们的问题无关,页面是空白的,但是因为加载它时出现了一些奇怪的问题,与渲染管道无关。顺便说一句。。。同样在我的例子中,键盘/输入性能非常糟糕(并且随着页面复杂性的增加而降低),因此我选择在运行时使用JQuery,在选择HTML输入时触发本机输入覆盖。它不是很优雅,但本机输入工作完美无瑕,文本选择/剪切/粘贴并不令人沮丧……一个不会降低性能的替代方案:)可能不是最好的解决方案,但对我的案例唯一有效。这是可行的,但正如@Scarmysun所说的,不适合我,但我建议关闭硬件acc
@Override
    public void onScaleChanged(WebView view, float oldScale, float newScale) {
        if (view != null) {
            view.invalidate();
        }
    }