2011-03-03 7 views
11

Este problema me vuelve loco. Extraño algunos conocimientos básicos pero muy importantes sobre cómo manejar operaciones largas en un nuevo hilo creado dentro de una actividad y cómo modificar los componentes de visualización como el texto y demás después de la larga operación.La actividad ha filtrado la ventana [email protected] que se agregó originalmente aquí

Primero te voy a mostrar la parte de mi código en la que se presenta este problema:

mProgressDialog = ProgressDialog.show(mContext, "Tripplanner", "please wait...", true, false); 
connectAndGetRoute(); 


private void connectAndGetRoute(){ 

    new Thread(){ 
     @Override 
     public void run() { 
      try { 
      if(!connectTo9292ov()) return;// conncetto9292ov() connects to a website, parses the reasult into an arraylist. The arraylist contains route. 

      } catch(UnknownHostException e){ 
       Toast.makeText(mContext, "failed to connect to server", Toast.LENGTH_LONG).show(); 
      }catch (ClientProtocolException e) { 
       Toast.makeText(mContext, "failed to connect to server", Toast.LENGTH_LONG).show();     
     } catch (IOException e) { 
       Toast.makeText(mContext, "failed to connect to server", Toast.LENGTH_LONG).show(); 
      } 

      handler.post(runConnection); 
     } 

    }.start(); 

    handler = new Handler(); 
    runConnection = new Runnable(){ 
     @Override 
     public void run() { 
      mProgressDialog.dismiss(); 
      showOnScreen(); 
     } 
    }; 
} 

y este es el error que consigo:

ERROR/WindowManager(8297): Activity mp.tripplanner.OvPlanner has leaked window [email protected] that was originally added here 
ERROR/WindowManager(8297): android.view.WindowLeaked: Activity mp.tripplanner.OvPlanner has leaked window [email protected] that was originally added here 
ERROR/WindowManager(8297): at android.view.ViewRoot.<init>(ViewRoot.java:251) 
ERROR/WindowManager(8297): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148) 
ERROR/WindowManager(8297): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91) 
ERROR/WindowManager(8297): at android.view.Window$LocalWindowManager.addView(Window.java:424) 
ERROR/WindowManager(8297): at android.app.Dialog.show(Dialog.java:241) 
ERROR/WindowManager(8297): at android.app.ProgressDialog.show(ProgressDialog.java:107) 
ERROR/WindowManager(8297): at android.app.ProgressDialog.show(ProgressDialog.java:95) 
ERROR/WindowManager(8297): at mp.tripplanner.OvPlanner$3.onClick(OvPlanner.java:351) 
ERROR/WindowManager(8297): at android.view.View.performClick(View.java:2408) 
ERROR/WindowManager(8297): at android.view.View$PerformClick.run(View.java:8817) 
ERROR/WindowManager(8297): at android.os.Handler.handleCallback(Handler.java:587) 
ERROR/WindowManager(8297): at android.os.Handler.dispatchMessage(Handler.java:92) 
ERROR/WindowManager(8297): at android.os.Looper.loop(Looper.java:144) 
ERROR/WindowManager(8297): at android.app.ActivityThread.main(ActivityThread.java:4937) 
ERROR/WindowManager(8297): at java.lang.reflect.Method.invokeNative(Native Method) 
ERROR/WindowManager(8297): at java.lang.reflect.Method.invoke(Method.java:521) 
ERROR/WindowManager(8297): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 
ERROR/WindowManager(8297): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 
ERROR/WindowManager(8297): at dalvik.system.NativeStart.main(Native Method) 

Pero otro mensaje de error se escribe en el registro antes de la de arriba, la cual es:

ERROR/AndroidRuntime(8297): FATAL EXCEPTION: Thread-9 
ERROR/AndroidRuntime(8297): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare() 
ERROR/AndroidRuntime(8297): at android.os.Handler.<init>(Handler.java:121) 
ERROR/AndroidRuntime(8297): at android.widget.Toast.<init>(Toast.java:68) 
ERROR/AndroidRuntime(8297): at android.widget.Toast.makeText(Toast.java:231) 
ERROR/AndroidRuntime(8297): at mp.tripplanner.OvPlanner$4.run(OvPlanner.java:371) 

Gracias por su ayuda.

Respuesta

4

Debe crear su Handler en su subproceso de interfaz de usuario para que pueda actualizar la interfaz de usuario. me permitiría utilizar el método sendMessage del manipulador, en lugar de publicar un ejecutable:

private static final int HANDLER_MESSAGE_ERROR = 0; 
private static final int HANDLER_MESSAGE_COMPLETED = 1; 
... 
private void connectAndGetRoute(){ 
    new Thread(){ 
     @Override 
     public void run() { 
      try { 
       if(!connectTo9292ov()) return; 

      } catch(UnknownHostException e){ 
       sendMessage(HANDLER_MESSAGE_ERROR); 
      } catch (ClientProtocolException e) { 
       sendMessage(HANDLER_MESSAGE_ERROR); 
      } catch (IOException e) { 
       sendMessage(HANDLER_MESSAGE_ERROR); 
      } finally { 
       sendMessage(HANDLER_MESSAGE_COMPLETED); 
      } 
     } 
     private void sendMessage(int what){ 
      Message msg = Message.obtain(); 
      msg.what = what; 
      mHandler.sendMessage(msg); 
     } 
    }.start(); 

} 
... 
private Handler mHandler = new Handler(){ 
    @Override 
    public void handleMessage(Message msg) { 
     switch(msg.what){ 
     case HANDLER_MESSAGE_ERROR: 
      Toast.makeText(mContext, "failed to connect to server", Toast.LENGTH_LONG).show(); 
      break; 
     case HANDLER_MESSAGE_COMPLETED: 
      mProgressDialog.dismiss(); 
      showOnScreen(); 
      break; 
     default: 
      Log.w("MyTag","Warning: message type \""+msg.what+"\" not supported"); 
     } 
    } 
} 
+1

Thaks mucho, esto resolvió el problema. Solo quería saber si recomienda usar sendMessage del controlador en lugar de publicar un ejecutable. – mnish

+1

@mnish, ambos métodos deberían funcionar, solo me parece más fácil hacer un seguimiento de las actualizaciones de UI si están todas en un solo lugar. La separación de responsabilidades es más fácil de ver usando 'sendMessage', por lo que me resulta más fácil depurar. –

+0

claro gracias! – mnish

1

Solo una idea rápida.

Creo que son tus mensajes tostados dentro del hilo. Intenta comentarlos.

Si aún desea mostrar mensajes, guarde el estado de su hilo y manipúlelo en su controlador. Llame para que su manejador de bloque finally

mProgressDialog = ProgressDialog.show(mContext, "Tripplanner", "please wait...", true, false); 
connectAndGetRoute(); 


private void connectAndGetRoute(){ 

    new Thread(){ 
     @Override 
     public void run() { 
      try { 
      if(!connectTo9292ov()) return;// conncetto9292ov() connects to a website, parses the reasult into an arraylist. The arraylist contains route. 

      } catch(UnknownHostException e){ 
       // an int member of your activity 
       threadStatus = 404; 
       // Toast.makeText(mContext, "failed to connect to server", Toast.LENGTH_LONG).show(); 
      }catch (ClientProtocolException e) { 
       threadStatus = 404; 
       // Toast.makeText(mContext, "failed to connect to server", Toast.LENGTH_LONG).show();     
     } catch (IOException e) { 
       threadStatus = 404; 
       // Toast.makeText(mContext, "failed to connect to server", Toast.LENGTH_LONG).show(); 
      } 
      finally { 
      handler.post(runConnection);} 
     } 

    }.start(); 

    handler = new Handler(); 
    runConnection = new Runnable(){ 
     @Override 
     public void run() { 
      if (threadStatus == 404) { Toast.makeText(mContext, "failed to connect to server", Toast.LENGTH_LONG).show();} 
      else { 
      mProgressDialog.dismiss(); 
      showOnScreen();} 
     } 
    }; 
} 
+0

acertaste, y adivinado también, pero no estaba seguro, y todavía no saben cómo SolveIT. Porque no entiendo la solución que ofreces: D. ¿podría decirme qué quiere decir con guardar el estado del hilo y cómo lo hago? De hecho, necesito más explicaciones sobre tu solución: D. Lo siento. – mnish

+1

modifiqué tu código un poco. Si me preguntas por qué razón, entonces no puedes actualizar tu interfaz de usuario del hilo. Deberías hacerlo afuera. – Tima

+0

y eche un vistazo a la respuesta de @ Olsavage – Tima

1

Código de ejemplo:

new Thread(new Runnable() {     
       @Override 
       public void run() { 
        doNotUIthings(); 
        updateUI.sendEmptyMessage(0); //Update ui in UI thread 
       } 
       private Handler updateUI = new Handler(){ 
        @Override 
        public void dispatchMessage(Message msg) { 
         super.dispatchMessage(msg); 
         updateUI(); 
        } 
       }; 
      }).start(); 

Pero recomiendo usar AsyncTask en lugar de hebras de Java.

+0

muchas gracias. Nunca pensé en esto en realidad. Aunque no sé cómo funciona esto, definitivamente consideraré usarlo en el futuro si el problema actual vuelve a ocurrir. Pero por ahora continuaré con la solución ofrecida por Dave.c porque funciona muy bien para mí. – mnish

Cuestiones relacionadas