完整的错误日志如下:
2021-11-04 18:05:00.826 7793-8402/com.cloudmind.vegarena E/AndroidRuntime: FATAL EXCEPTION: Thread-15
Process: com.cloudmind.vegarena, PID: 7793
java.lang.RuntimeException: java.lang.Throwable: A WebView method was called on thread 'Thread-15'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 2) {d4104b1} called on null, FYI main Looper is Looper (main, tid 2) {d4104b1})
at android.webkit.WebView.checkThread(WebView.java:2549)
at android.webkit.WebView.loadUrl(WebView.java:945)
at com.cloudmind.activity.WebViewHomeActivity$GetPingLocal.run(WebViewHomeActivity.java:836)
Caused by: java.lang.Throwable: A WebView method was called on thread 'Thread-15'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 2) {d4104b1} called on null, FYI main Looper is Looper (main, tid 2) {d4104b1})
at android.webkit.WebView.checkThread(WebView.java:2544)
at android.webkit.WebView.loadUrl(WebView.java:945)
at com.cloudmind.activity.WebViewHomeActivity$GetPingLocal.run(WebViewHomeActivity.java:836)
从日志中可以得知,在线程 “Thread-15”中操作了 webView ,也就是说在非主线程中,操作了UI 控件。看一下我调用的过程 getPing 方法开启线程,线程执行完毕handler 发消息,刷新WebView;看似没问题的代码,可他偏偏就崩溃了。。。
@JavascriptInterface
public void getPing( String ip) {
// Log.e(TAG, " 测速ip = " + ip);
GetPingLocal getPingLocal = new GetPingLocal(ip);
getPingLocal.start();
}
/***
* 通过 jni 测速
*/
class GetPing extends Thread {
@Override
public void run() {
super.run();
try {
new NetworkUtils().checkIP("ip", "port");
} catch (Exception e) {
e.printStackTrace();
}
Message message = new Message();
message.what = 222;
message.arg1 = 1;
handler.sendMessage(message);
}
}
Handler handler1 = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case 222:
webView.loadUrl("www.baidu.com");
break;
}
}
};
事情(需求逻辑)是这样的:
开启线程的是在getPing() 方法中,然后这个方法呢是给 h5 调用 ,所以用@JavascriptInterface 修饰。 紧接着就排查到底为什么不是主线程(main),在getPing 方法中增加打印
Log.i("getping", "线程 - "+Thread.currentThread().getName());
果然发现了端倪 经过日志打印,被 @JavascriptInterface 修饰的方法getPing()方法,已经不属于主线程了,而是 JavaBridge,,,,所以线程执行完毕,handler 发消息返回的不是主线程,在非UI 线程中操作UI所以就崩溃了呗。。。。
找到原因那么问题就好解决了, 用post 不就返回到主线程了么,上正确代码
class GetPing extends Thread {
@Override
public void run() {
super.run();
try {
new NetworkUtils().checkIP("ip", "port");
} catch (Exception e) {
e.printStackTrace();
}
handler.post(new Runnable() {
@Override
public void run() {
webView.loadUrl("www.baidu.com");
}
});
}
}
知识点:
1.被h5 调用的 用 @JavascriptInterface 修饰的方法不属于main 线程,而是JavaBridge。
2.handler.post 方法,可以返回到主线程。