2012-02-25 50 views
5

由于某些原因,我必须在我的Android应用程序中使用WebView,并且业务逻辑的一部分包含在JavaScript中(我使用addJavascriptInterface()运行它)。问题是我无法从绑定到脚本的对象修改我的应用程序的UI组件。这是在文档中解释说:Android上的JavaScript访问UI

注:绑定到你的JavaScript运行在另一个线程 ,而不是在它构建了线程的对象。

我想知道是否有解决此问题的一些解决方法?

回答

13

您需要将Handler实例传递给您的JavaScript接口并使用它将信息发布到那里。如果此处理程序将在UI线程上创建,则runnables posted there也将在UI线程上调用。

Handler mHandler = new Handler(); // must be created on UI thread, e.g. in Activity onCreate 

// from javascript interface... 
mHandler.post(new Runnable() { 
    @Override 
    public void run() { 
     // code here will run on UI thread 
    } 
}); 

另一种解决方法是使用Activity的方法runOnUIThread

mActivity.runOnUIThread(new Runnable() { 
    @Override 
    public void run() { 
     // code here will run on UI thread 
    } 
}); 
+1

非常感谢!这确实有一招:) – 2012-02-25 23:20:13

+0

您可以随时使用'new Handler(Looper.getMainLooper())'使Handler使用UI线程。 – ImMathan 2016-10-28 12:29:32

1

假设你是一个片段内,你在你的JavaScript界面​​代码做getActrivity().runOnUIThread(...)。有可能在WebViewCoreThread执行JavaScript接口代码时,片段与活动分离,并且getActivity()将返回null,从而导致引发NullPointerException。一个安全的方法是使用一个Handler,如下例所示。另外,确保JavaScript界面​​对UI组件使用WeakReferences,因为它们需要在执行Javascript界面​​之前进行垃圾收集。

myWebView.addJavascriptInterface(new Object() { 
     private Handler handler = new Handler(); 
     private WeakReference<ProgressBar> progressBarRef = new WeakReference<ProgressBar>(
       myWebViewProgressBar); 
     private WeakReference<WebView> myWebViewRef = new WeakReference<WebView>(
       myWebView); 

     @SuppressWarnings("unused") 
     public void onFirstImageLoad() { 

      handler.post(new Runnable() { 
       @Override 
       public void run() { 
        ProgressBar progressBar = progressBarRef.get(); 
        WebView webView = myWebViewRef.get(); 
        if (progressBar != null) { 
         progressBar.setVisibility(View.GONE); 
        } 
        if (webView != null) { 
         webView .setVisibility(View.VISIBLE); 
        } 
       } 
      }); 
     } 
    }, "jsInterface");