2012-02-25 8 views
5

Por alguna razón tengo que usar WebView en mi aplicación Android y parte de la lógica empresarial está contenida en JavaScript (lo ejecuto usando addJavascriptInterface()). El problema es que no puedo modificar los componentes de la interfaz de usuario de mi aplicación desde el objeto enlazado al script. Eso se explica en la documentación:Acceso a la IU desde JavaScript en Android

Nota: El objeto que está obligado a su código JavaScript se ejecuta en otro hilo y no en el hilo en el que fue construido.

Me pregunto si hay alguna solución para este problema?

Respuesta

13

Debe pasar la instancia Handler a su interfaz de JavaScript y usarla para publicar allí los ejecutables. Si este controlador se creará en el hilo de la interfaz de usuario, los ejecutables posted there también se invocarán en el hilo de la interfaz de usuario.

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 
    } 
}); 

Otra solución consiste en utilizar el método Activity 's runOnUIThread

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

¡Muchas gracias! Eso hizo un truco :) –

+0

Siempre puedes hacer 'new Handler (Looper.getMainLooper())' para hacer que Handler use el hilo de UI. – ImMathan

1

Supongamos que está dentro de un fragmento y que está haciendo getActrivity().runOnUIThread(...) en el código de interfaz de Javascript. Es posible que para el momento en que WebViewCoreThread ejecute el código de la interfaz de Javascript, el fragmento se separe de la actividad y getActivity() devolverá un valor nulo que dará como resultado una excepción NullPointerException. Una forma segura de hacerlo es utilizar un controlador como se muestra en el siguiente ejemplo. Además, asegúrese de que la interfaz de JavaScript use WeakReferences para los componentes de la interfaz de usuario en caso de que sea necesario recolectarlos antes de que se ejecute la interfaz de 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"); 
Cuestiones relacionadas