2012-02-25 52 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");