android webview.loadUrl将不会加载另一个网页

在我简单的Android应用程序中,我编程加载WebView中的网页。 它最初是从一个默认的网页开始的,下一个是根据第一个用户的input加载的。 JavaScript通过消息将信息传递回Android的一面。 一切工作正常,除非第二个网页不加载,无论我做什么,我给的是哪个url。 当我加载第二个testing时,会出现一个警告:“所有WebView方法必须在同一个线程上调用”。 但据我所知,我不使用multithreading,也不需要使用multithreading。

以下是相关的代码:

public class MainActivity extends Activity { public WebView myWebView; public int state; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_main); myWebView = (WebView) findViewById(R.id.webview); WebSettings myWebViewSettings = myWebView.getSettings(); myWebViewSettings.setJavaScriptEnabled(true); myWebViewSettings.setDomStorageEnabled(true); myWebViewSettings.setAllowFileAccessFromFileURLs(true); myWebViewSettings.setAllowUniversalAccessFromFileURLs(true); myWebView.addJavascriptInterface(new JavascriptHandler(), "cpjs"); state = 0; loadNextTest(); } public void webviewLoadURL(String url) { Log.d("app", "now loading " + url); myWebView.clearHistory(); myWebView.clearFormData(); myWebView.clearCache(true); myWebView.loadUrl(url); } final class JavascriptHandler { @JavascriptInterface public void sendToAndroid(String text) { if (text.equals("confirmed at target")) { loadNextTest(); } } } public void loadNextTest() { Log.d("app", "now loading test " + (state + 1)); if (state == 0) { webviewLoadURL("file:///android_asset/test1.html"); state = state + 1; } else if (state == 1) { webviewLoadURL("file:///android_asset/test2.html"); // webviewLoadURL("http://www.google.com"); state = state + 1; } else { webviewLoadURL("file:///android_asset/test3.html"); } } } 

这里是相关的日志行:

 02-22 09:12:32.250: V/WebViewChromium(15117): Binding Chromium to the background looper Looper (main, tid 1) {41c7ec00} 02-22 09:12:32.250: I/chromium(15117): [INFO:library_loader_hooks.cc(112)] Chromium logging enabled: level = 0, default verbosity = 0 02-22 09:12:32.255: I/BrowserProcessMain(15117): Initializing chromium process, renderers=0 02-22 09:12:32.265: W/chromium(15117): [WARNING:proxy_service.cc(888)] PAC support disabled because there is no system implementation 02-22 09:12:32.315: D/dalvikvm(15117): GC_FOR_ALLOC freed 86K, 5% free 3217K/3364K, paused 8ms, total 8ms 02-22 09:12:32.315: I/dalvikvm-heap(15117): Grow heap (frag case) to 4.273MB for 1127536-byte allocation 02-22 09:12:32.325: D/dalvikvm(15117): GC_FOR_ALLOC freed <1K, 4% free 4318K/4468K, paused 11ms, total 11ms 02-22 09:12:32.345: D/dalvikvm(15117): GC_CONCURRENT freed <1K, 4% free 4317K/4468K, paused 1ms+6ms, total 17ms 02-22 09:12:32.365: D/app(15117): now loading test 1 02-22 09:12:32.365: D/app(15117): now loading file:///android_asset/test1.html 02-22 09:12:32.450: D/mali_winsys(15117): new_window_surface returns 0x3000 02-22 09:12:32.460: I/Icing(794): Indexing 5AA949AFB589F1D17D8668589402D01E615E228D from com.google.android.googlequicksearchbox 02-22 09:12:32.500: D/OpenGLRenderer(15117): Enabling debug mode 0 02-22 09:12:32.505: W/AwContents(15117): nativeOnDraw failed; clearing to background color. 02-22 09:12:32.540: I/ActivityManager(447): Displayed com.example.myApp/.MainActivity: +344ms 02-22 09:12:32.550: W/AwContents(15117): nativeOnDraw failed; clearing to background color. 02-22 09:12:32.635: I/Icing(794): Indexing done 5AA949AFB589F1D17D8668589402D01E615E228D 02-22 09:12:32.945: I/chromium(15117): [INFO:async_pixel_transfer_manager_android.cc(56)] Async pixel transfers not supported 02-22 09:12:32.960: I/chromium(15117): [INFO:async_pixel_transfer_manager_android.cc(56)] Async pixel transfers not supported 02-22 09:12:33.180: E/AndroidProtocolHandler(15117): Unable to open asset URL: file:///android_asset/backend/images/ajax-loader.gif 02-22 09:12:46.010: D/app(15117): now loading test 2 02-22 09:12:46.010: D/app(15117): now loading http://www.google.com 02-22 09:12:46.020: W/WebView(15117): java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {41c7ec00} called on Looper (JavaBridge, tid 271) {41c6f5c8}, FYI main Looper is Looper (main, tid 1) {41c7ec00}) 02-22 09:12:46.020: W/WebView(15117): at android.webkit.WebView.checkThread(WebView.java:2063) 02-22 09:12:46.020: W/WebView(15117): at android.webkit.WebView.clearHistory(WebView.java:1399) 02-22 09:12:46.020: W/WebView(15117): at com.example.myApp.MainActivity.webviewLoadURL(MainActivity.java:68) 02-22 09:12:46.020: W/WebView(15117): at com.example.myApp.MainActivity.loadNextTest(MainActivity.java:91) 02-22 09:12:46.020: W/WebView(15117): at com.example.myApp.MainActivity$JavascriptHandler.sendToAndroid(MainActivity.java:78) 02-22 09:12:46.020: W/WebView(15117): at com.android.org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method) 02-22 09:12:46.020: W/WebView(15117): at com.android.org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:27) 02-22 09:12:46.020: W/WebView(15117): at android.os.Handler.dispatchMessage(Handler.java:102) 02-22 09:12:46.020: W/WebView(15117): at android.os.Looper.loop(Looper.java:136) 02-22 09:12:46.020: W/WebView(15117): at android.os.HandlerThread.run(HandlerThread.java:61) 02-22 09:12:46.030: W/System.err(15117): java.lang.RuntimeException: java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {41c7ec00} called on Looper (JavaBridge, tid 271) {41c6f5c8}, FYI main Looper is Looper (main, tid 1) {41c7ec00}) 02-22 09:12:46.035: W/System.err(15117): at android.webkit.WebView.checkThread(WebView.java:2073) 02-22 09:12:46.035: W/System.err(15117): at android.webkit.WebView.clearHistory(WebView.java:1399) 02-22 09:12:46.035: W/System.err(15117): at com.example.myApp.MainActivity.webviewLoadURL(MainActivity.java:68) 02-22 09:12:46.035: W/System.err(15117): at com.example.myApp.MainActivity.loadNextTest(MainActivity.java:91) 02-22 09:12:46.035: W/System.err(15117): at com.example.myApp.MainActivity$JavascriptHandler.sendToAndroid(MainActivity.java:78) 02-22 09:12:46.035: W/System.err(15117): at com.android.org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method) 02-22 09:12:46.040: W/System.err(15117): at com.android.org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:27) 02-22 09:12:46.040: W/System.err(15117): at android.os.Handler.dispatchMessage(Handler.java:102) 02-22 09:12:46.040: W/System.err(15117): at android.os.Looper.loop(Looper.java:136) 02-22 09:12:46.040: W/System.err(15117): at android.os.HandlerThread.run(HandlerThread.java:61) 02-22 09:12:46.040: W/System.err(15117): Caused by: java.lang.Throwable: A WebView method was called on thread 'JavaBridge'. All WebView methods must be called on the same thread. (Expected Looper Looper (main, tid 1) {41c7ec00} called on Looper (JavaBridge, tid 271) {41c6f5c8}, FYI main Looper is Looper (main, tid 1) {41c7ec00}) 02-22 09:12:46.045: W/System.err(15117): at android.webkit.WebView.checkThread(WebView.java:2063) 02-22 09:12:46.045: W/System.err(15117): ... 9 more 

任何帮助表示赞赏。 谢谢。

正如教授T提到的那样,有许multithreading在WebView的幕后运行,并且JavaScript通过JavaScript接口对象的callback在后台线程上进行。

你可以用loadNextTest这样的代码实现你喜欢的loadNextTest

 myWebView.post(new Runnable() { @Override public void run() { webviewLoadURL("file:///android_asset/test1.html"); } }); 

另请注意,你的statevariables也会被写在JavaScript后台线程上,所以你也需要同步你的读/写,如果它们来自其他线程。

绑定到您的JavaScript的对象运行在另一个线程中,而不是在它所在的线程中运行。

你可以强制所有的webview url加载完成在主线程,检查了这一点:

在主线程上运行callback