我正在开发一个名为Lightning Browser的开源浏览器,我在Android(4.2.2)的最新更新时遇到了一些麻烦。
在触摸视图之前,WebViews将无法完全呈现。它只发生在最新的Android版本上。在4.2.1上,WebView呈现完全正常。我使用Nexus 7进行开发,在收到4.2.2更新后,浏览器停止渲染。其他用户也经历过这种情况,并且仅在4.2.2上多次确认。它正在针对API级别16和17进行,但我看到了一个针对API级别9的WebKit浏览器,没有出现此问题。
我试图使用我在Stack Overflow(Android WebView renders blank/white, view doesn't update on css changes or HTML changes, animations are choppy)上找到的问题的解决方案来解决这个问题。但是,单独将WebView的RenderPriority设置为high并不能解决它...在不触及的情况下使其呈现的唯一方法是将invalidate()命令放在WebView的OnDraw()方法中。这会导致WebView不断重绘。这样(有点),动画是平滑的,页面加载非常快,但它会导致WebView的性能下降。
我也看过这个问题(与我的非常相似),但没有好的答案。 Android WebView Fails to Completely Render Content Until User Interaction
通过性能下降,我的意思是输入。文本输入滞后,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上问过的第一个问题,如果我不清楚或者我做错了什么,请原谅我。
编辑: 我发现这个问题here关于一个类似的问题已经解决,问题是,我不明白答案甚至意味着什么。如果有人能够启发我可能会有所帮助。
我在logcat
中遇到此错误E/chromium(1243): external/chromium/net/disk_cache/backend_impl.cc:2022: [0705/172030:ERROR:backend_impl.cc(2022)] Corrupt Index file
答案 0 :(得分:9)
所以我终于找到了导致WebView无法渲染的问题。我正在WebView的WebViewClient中启动并停止drawable的动画。这个drawable只是一个刷新按钮,在页面加载时旋转......简单吧?
在浏览器的非全屏模式下,旋转drawable和WebView都是同一父项的子项,而在全屏模式下,drawable成为WebView的子项。不知何故,通过在页面加载时启动动画并在完成时停止它(在全屏幕中),应用程序决定旋转drawable是需要所有绘图能力而WebView从不绘制的。当处于全屏模式并且drawable成为WebView的子级时,WebView的渲染优先级高于drawable,并且绘制得很好。
故事的寓意是...... WebViews喜欢成为最优先考虑的视图。如果有其他视图获得更高的优先级,则它们将无法正确绘制。
我不是动画方面的专家,所以我需要重新思考我现在如何设置drawable动画,以免打断WebView。
希望这是有道理的。谢谢你的阅读。
答案 1 :(得分:4)
禁用清单上的硬件加速:
机器人:硬件加速= “假”
答案 2 :(得分:2)
请查看@Olivier在Android WebView renders blank/white, view doesn't update on css changes or HTML changes, animations are choppy上的最后一个答案,他在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);
玩毫秒值......
希望这有助于某人!
答案 3 :(得分:2)
旋转手机时缩放比例存在问题,这将导致此问题,不会绘制部分或整个页面。要在WebViewClient实现中解决此覆盖onScaleChanged并使视图无效。这应该会在需要时强制重绘。
@Override
public void onScaleChanged(WebView view, float oldScale, float newScale) {
if (view != null) {
view.invalidate();
}
}