2010-02-10 17 views
7

Estoy jugando con Android, y estoy creando una aplicación de Twitter simple para probar lo que he aprendido hasta ahora. Pero me encontré con un problema que no entiendo. Creé un hilo para buscar los tweets, no hubo problemas allí, pero luego agregué un ProgressDialog para mostrar cuándo se estaba ejecutando ese hilo. Hacerlo causó un comportamiento muy inusual. Si el usuario gira de orientación vertical a orientación horizontal, el programa se comporta como se esperaba, no hay problemas, pero si luego gira hacia atrás, el programa se bloquea y se filtra una ventana.Android: bloqueo en la rotación, horizontal a vertical

El problema solo ocurre en un conmutador de diseño horizontal a vertical. Sé de los problemas de si intenta girar mientras se está ejecutando el cuadro de diálogo, pero me he asegurado de que el cuadro de diálogo haya terminado de ejecutarse y se haya descartado antes de rotar y aún se bloqueará. Aquí está mi código:

package com.onesmartpuppy.puppytweet; 
import java.util.ArrayList; 
import com.github.droidfu.widgets.WebImageView; 
import winterwell.jtwitter.Twitter; 
import winterwell.jtwitter.Twitter.Status; 
import android.app.ListActivity; 
import android.app.ProgressDialog; 
import android.content.Context; 
import android.content.Intent; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Message; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.view.View.OnClickListener; 
import android.widget.ArrayAdapter; 
import android.widget.Button; 
import android.widget.TextView; 

public class PuppyTweet extends ListActivity implements OnClickListener { 

    private ProgressDialog m_ProgressDialog = null; 
    private ArrayList<Status> messages = null; 
    private TweetAdapter m_adapter; 

    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
     messages = new ArrayList<Status>(); 
     this.m_adapter = new TweetAdapter(this, R.layout.row, messages); 
     setListAdapter(this.m_adapter); 

     setupButtons(); 

     m_ProgressDialog = ProgressDialog.show(this,  
      "Please wait...", "Retrieving tweets ...", true); 

     Runnable findTweets = new Runnable(){ 
      @Override 
      public void run() { 

      try { 
       messages = new ArrayList<Status>(); 

       Twitter ourTwitter = new Twitter("*****", "******"); 
       messages = (ArrayList<Status>) ourTwitter.getFriendsTimeline(); 

       Thread.sleep(1000); 
       Log.i("ARRAY", ""+ messages.size()); 
      } catch (Exception e) { 
       Log.e("BACKGROUND_PROC", e.getMessage()); 
      } 
       handler.sendEmptyMessage(0); 
      } 
     }; 

     Thread thread = new Thread(null, findTweets, "FindTweets"); 
     thread.start(); 
    } 



    private void setupButtons() 
    { 
    Button refreshButton = (Button) findViewById(R.id.refresh_button); 
    refreshButton.setOnClickListener(this); 
    Button settingsButton = (Button) findViewById(R.id.settings_button); 
    settingsButton.setOnClickListener(this); 
    Button tweetButton = (Button) findViewById(R.id.update_button); 
    tweetButton.setOnClickListener(this); 
    } 



@Override 
public void onClick(View v) { 
    switch (v.getId()) 
    { 
    case R.id.settings_button: 
    break; 
    case R.id.update_button: 
    break; 
    case R.id.refresh_button: 
    break; 
    default: 
    break; 
    } 
} 

private Handler handler = new Handler() { 

     @Override 
     public void handleMessage(Message msg) { 
      if(messages != null && messages.size() > 0){ 
       m_adapter.clear(); 
       m_adapter.notifyDataSetChanged(); 
       for(int i=0;i<messages.size();i++) 
        m_adapter.add(messages.get(i)); 
      } 
      m_ProgressDialog.dismiss(); 
      m_adapter.notifyDataSetChanged(); 
     } 
    }; 


    private class TweetAdapter extends ArrayAdapter<Status> { 

     private ArrayList<Status> items; 

     public TweetAdapter(Context context, int textViewResourceId, ArrayList<Status> items) { 
       super(context, textViewResourceId, items); 
       this.items = items; 
     } 

     @Override 
     public View getView(int position, View convertView, ViewGroup parent) { 
       View v = convertView; 
       if (v == null) { 
        LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
        v = vi.inflate(R.layout.row2, null); 
       } 
       Status o = (Status) items.get(position); 

       if (o != null) { 
       WebImageView img = (WebImageView) v.findViewById(R.id.webimage);     
         TextView tt = (TextView) v.findViewById(R.id.toptext); 
         TextView bt = (TextView) v.findViewById(R.id.bottomtext); 
         if (tt != null) { 
          tt.setText("Name: " + o.user.name);       } 
         if(bt != null){ 
          bt.setText("Status: " + o.getText()); 
         } 
         if (img !=null) { 
         img.setImageUrl(o.getUser().profileImageUrl.toString()); 
          img.loadImage(); 
         } 
       } 
       return v; 
     } 


    } 
} 

aquí está el LogCat desde donde se bloquea:

02-10 16:01:05.237: INFO/ActivityManager(63): Config changed: { scale=1.0 imsi=310/260 loc=ld_US touch=3 keys=2/1/2 nav=3/1 orien=2 layout=18} 
02-10 16:01:05.344: WARN/UsageStats(63): Something wrong here, didn't expect com.onesmartpuppy.puppytweet to be resumed 
02-10 16:01:05.384: INFO/WindowManager(63): Setting rotation to 0, animFlags=0 
02-10 16:01:05.394: INFO/ActivityManager(63): Config changed: { scale=1.0 imsi=310/260 loc=ld_US touch=3 keys=2/1/2 nav=3/1 orien=1 layout=18} 
02-10 16:01:05.504: WARN/UsageStats(63): Something wrong here, didn't expect com.onesmartpuppy.puppytweet to be resumed 
02-10 16:01:05.704: ERROR/WindowManager(227): Activity com.onesmartpuppy.puppytweet.PuppyTweet has leaked window [email protected] that was originally added here 
02-10 16:01:05.704: ERROR/WindowManager(227): android.view.WindowLeaked: Activity com.onesmartpuppy.puppytweet.PuppyTweet has leaked window [email protected] that was originally added here 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.view.ViewRoot.<init>(ViewRoot.java:227) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.view.Window$LocalWindowManager.addView(Window.java:424) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.app.Dialog.show(Dialog.java:239) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.app.ProgressDialog.show(ProgressDialog.java:107) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.app.ProgressDialog.show(ProgressDialog.java:90) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at com.onesmartpuppy.puppytweet.PuppyTweet.onCreate(PuppyTweet.java:39) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2417) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2470) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3573) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.app.ActivityThread.access$2300(ActivityThread.java:119) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1825) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.os.Handler.dispatchMessage(Handler.java:99) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.os.Looper.loop(Looper.java:123) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at android.app.ActivityThread.main(ActivityThread.java:4310) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at java.lang.reflect.Method.invokeNative(Native Method) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at java.lang.reflect.Method.invoke(Method.java:521) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 
02-10 16:01:05.704: ERROR/WindowManager(227):  at dalvik.system.NativeStart.main(Native Method) 
02-10 16:01:06.344: INFO/global(227): Default buffer size used in BufferedReader constructor. It would be better to be explicit if an 8k-char buffer is required. 
02-10 16:01:06.624: DEBUG/dalvikvm(227): GC freed 6082 objects/479568 bytes in 77ms 
02-10 16:01:07.374: DEBUG/dalvikvm(227): GC freed 11982 objects/709808 bytes in 83ms 
02-10 16:01:07.394: INFO/global(227): Default buffer size used in BufferedReader constructor. It would be better to be explicit if an 8k-char buffer is required. 
02-10 16:01:07.564: DEBUG/dalvikvm(227): GC freed 95 objects/79880 bytes in 68ms 
02-10 16:01:07.704: DEBUG/dalvikvm(227): GC freed 8 objects/38992 bytes in 65ms 
02-10 16:01:08.174: DEBUG/dalvikvm(63): GC freed 5407 objects/257208 bytes in 174ms 
02-10 16:01:08.194: INFO/ARRAY(227): 20 
02-10 16:01:08.204: DEBUG/AndroidRuntime(227): Shutting down VM 
02-10 16:01:08.204: WARN/dalvikvm(227): threadid=3: thread exiting with uncaught exception (group=0x4001b188) 
02-10 16:01:08.204: ERROR/AndroidRuntime(227): Uncaught handler: thread main exiting due to uncaught exception 
02-10 16:01:08.214: ERROR/AndroidRuntime(227): java.lang.IllegalArgumentException: View not attached to window manager 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:355) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:200) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at android.view.Window$LocalWindowManager.removeView(Window.java:432) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at android.app.Dialog.dismissDialog(Dialog.java:280) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at android.app.Dialog.access$000(Dialog.java:73) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at android.app.Dialog$1.run(Dialog.java:109) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at android.app.Dialog.dismiss(Dialog.java:264) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at com.onesmartpuppy.puppytweet.PuppyTweet$1.handleMessage(PuppyTweet.java:104) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at android.os.Handler.dispatchMessage(Handler.java:99) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at android.os.Looper.loop(Looper.java:123) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at android.app.ActivityThread.main(ActivityThread.java:4310) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at java.lang.reflect.Method.invokeNative(Native Method) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at java.lang.reflect.Method.invoke(Method.java:521) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 
02-10 16:01:08.214: ERROR/AndroidRuntime(227):  at dalvik.system.NativeStart.main(Native Method) 
02-10 16:01:08.244: INFO/Process(63): Sending signal. PID: 227 SIG: 3 
02-10 16:01:08.244: INFO/dalvikvm(227): threadid=7: reacting to signal 3 
02-10 16:01:08.274: ERROR/dalvikvm(227): Unable to open stack trace file '/data/anr/traces.txt': Permission denied 
02-10 16:01:08.754: DEBUG/dalvikvm(227): GC freed 5986 objects/372656 bytes in 316ms 
02-10 16:01:09.829: INFO/ARRAY(227): 20 
02-10 16:01:09.955: INFO/Process(227): Sending signal. PID: 227 SIG: 9 
02-10 16:01:09.974: INFO/ActivityManager(63): Process com.onesmartpuppy.puppytweet (pid 227) has died. 
02-10 16:01:10.014: INFO/WindowManager(63): WIN DEATH: Window{43b653e0 com.onesmartpuppy.puppytweet/com.onesmartpuppy.puppytweet.PuppyTweet paused=false} 
02-10 16:01:10.014: INFO/WindowManager(63): WIN DEATH: Window{43c32b48 Please wait... paused=false} 
02-10 16:01:10.164: WARN/UsageStats(63): Unexpected resume of com.android.launcher while already resumed in com.onesmartpuppy.puppytweet 
02-10 16:01:10.314: WARN/InputManagerService(63): Got RemoteException sending setActive(false) notification to pid 227 uid 10023 
+2

Utiliza la funcionalidad * LogCat * de Android, deja las instrucciones de depuración con la clase 'Log' dentro de tu código y abre la ventana de perspectiva * LogCat * en Android y publica el seguimiento de la pila. Mostrará en qué línea se produjo la filtración de la ventana y tal vez una forma de cómo solucionarlo. –

+1

¿Tiene la stacktrace? –

+0

manejando los eventos onDestroy y onPause para matar ese hilo podría valer la pena. probablemente no sea el problema sin embargo. –

Respuesta

9

La excepción WindowLeaked en el registro que suele ocurrir cuando se tiene algún tipo de tarea asíncrona que está terminando después de la actividad que se inició es destruido

Cuando gira la pantalla, se recrea la actividad. Por el Android docs, debe guardar cualquier estado de instancia en el método onPause, lo que incluye asegurarse de que se detenga cualquier tarea asíncrona. Puede volver a crear en el método onCreate, utilizando el paquete guardado.

+2

Agregué otro descartar() en el método onPause para el cuadro de diálogo, solucionó todos los problemas. ¡Gracias! – Kelend

+0

Gracias por darme una mejor comprensión de este problema y por qué la solución funciona. ¡Este problema ha sido durante mucho tiempo! Ahora no hay WindowLeak ya que estoy descartando el diálogo de alerta personalizado en OnPause() de PreferenceActivity. Solo sucedería si el teléfono gira mientras se muestra el cuadro de diálogo. –

Cuestiones relacionadas