Android:来自 WebView 的 shouldOverrideUrlLoading 的 CalledFromWrongThreadException

标签 android multithreading sdk webview

我正在开发一个库,该库以某种方式在 Samsung Galaxy S1(api v7 - android 2.1)上发生 CalledFromWrongThread 异常崩溃。代码是这样的:

class MyWebViewClient extends WebViewClient {
    @Override
    public void shouldOverrideUrlLoading(WebView view, String url) {
        someListener.addToUiView();
    }
}

当然,还有实际抛出错误的方法(实现监听器回调):

View v;
public void addToUiView(){
    v.addView(new TextView(context)); //<-- this line is throwing the error on rare occasions
}

我跳过了中间的一些代码,但我没有在其他地方做任何奇怪的事情。另请注意:这种崩溃似乎只发生了非常小部分的时间。 (不一定是结论性的,因为并非每个人都报告他们的数据)。

还有人遇到过这个吗? WebCore 线程是否把事情弄乱了?

最佳答案

现在我还没有真正测试过这个,但我将尽我所知回答。也就是说,我的直觉告诉我,您只会间歇性地看到错误,因为来自 WebView(浏览器)的 Web 请求会发生不同程度的异步性,并且可能会利用线程池来完成此操作。基本上,有时它会并行请求资源,有时则不会。更糟糕的是,您可能只会在单个设备上看到此错误,因为 OEM 根据他们的偏好和意见(尤其是三星)优化操作系统级别代码(如 WebView 内部)。无论哪种方式,真正的问题是您正在一个绝对不能保证“UI 友好”的地方做一些“UI 相关”的事情......也就是说,在您获得子系统回调的任何地方。

问题的解决方案比解释简单得多:只需使用您的上下文(我假设是一个Activity)..

Activity 有一个名为 runOnUiThread(Runnable) 的内置函数这将防止可运行对象内的代码在错误的线程上运行。基本上,你的问题确实很常见,android 有一个内置的解决方案。 runOnUiThread 只会在需要时增加开销,换句话说,如果您的线程是 UI 线程,它只会运行 Runnable,如果不是,它会使用正确的 Handler(与 UI 线程关联的处理程序)来运行 Runnable

它应该是这样的:

View v;
public void addToUiView() {

    final Activity activity = (Activity) context;

    activity.runOnUiThread(new Runnable() {

        @Override
        public void run() {

            v.addView(new TextView(activity));
        }

    });
}

我将其编码在 SO 窗口内,因此我对任何严重错误表示歉意,希望有所帮助,如果您需要更多信息或这不能解决您的问题,请告诉我 -ck

关于Android:来自 WebView 的 shouldOverrideUrlLoading 的 CalledFromWrongThreadException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18434470/

相关文章:

Java/Android : Socket closed when offloading work to a thread pool

android - Eclipse - Gradle - Android SDK(未能针对 android-22 : . ...)

iPhone 应用程序因 Three20 "non-public API" "lineHeight"和 "previousViewController"被拒绝

ios - 当我添加到基本 SDK 中时,在 Xcode 8 中找不到 SDK,它会显示此信息

python - 多处理多线程GIL?

javascript - 如果用户多次单击元素,如何避免竞争条件?

安卓文件处理

android - 列表为空时有 2 个空布局组件

安卓用户界面问题

android - OSMDroid - 自定义标记