2011-07-07 13 views
40

Estoy usando ProgressDialog para evitar que el usuario interactúe mientras el dispositivo está descargando cosas desde Internet.ProgressDialog: cómo evitar la ventana filtrada

todo estaba funcionando bien hasta que mi cliente logrado producir este error:

"07-06 17:10:50.363: ERROR/WindowManager(8821): Activity android.pixelrain.framework.PixelRainActivity has leaked window [email protected] that was originally added here 
07-06 17:10:50.363: ERROR/WindowManager(8821): android.view.WindowLeaked: Activity android.pixelrain.framework.PixelRainActivity has leaked window [email protected] that was originally added here 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.view.ViewRoot.<init>(ViewRoot.java:251) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.view.Window$LocalWindowManager.addView(Window.java:424) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.app.Dialog.show(Dialog.java:241) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.app.ProgressDialog.show(ProgressDialog.java:107) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.app.ProgressDialog.show(ProgressDialog.java:90) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.pixelrain.HTTPHelper.DraftHelper.getDraft(DraftHelper.java:70) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.pixelrain.online.OnlineRetriver.getDraft(OnlineRetriver.java:312) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.pixelrain.HTTPHelper.DraftButtonGL.loadDraft(DraftButtonGL.java:72) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.pixelrain.HTTPHelper.DraftButtonGL.isTouched(DraftButtonGL.java:89) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.pixelrain.opengl.views.game.QuickStartGL.touchEnded(QuickStartGL.java:160) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.pixelrain.game.GameHandler.onTouchEvent(GameHandler.java:277) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.pixelrain.opengl.GLSurfaceViewChipmunk.onTouchEvent(GLSurfaceViewChipmunk.java:27) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.view.View.dispatchTouchEvent(View.java:3765) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:944) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:944) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:944) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1701) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1116) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.app.Activity.dispatchTouchEvent(Activity.java:2093) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1685) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.view.ViewRoot.handleMessage(ViewRoot.java:1802) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.os.Handler.dispatchMessage(Handler.java:99) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.os.Looper.loop(Looper.java:144) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.app.ActivityThread.main(ActivityThread.java:4937) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at java.lang.reflect.Method.invokeNative(Native Method) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at java.lang.reflect.Method.invoke(Method.java:521) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at dalvik.system.NativeStart.main(Native Method)" 

y no tengo ni idea de cómo solucionar este problema.

¿Alguna idea de qué causa esto y cómo resolverlo?

El registro se remonta el error de esta línea:

progressDialog = ProgressDialog.show(PixelRainActivity.staticThis, "",PixelRainActivity.staticThis.getResources().getString(R.string.draftProgressMessage), true); 

habría que resolver el problema si lo cambié a esto:

this.runOnUiThread(new Runnable() { 
      public void run() { 
       progressDialog = ProgressDialog.show(PixelRainActivity.staticThis, "",PixelRainActivity.staticThis.getResources().getString(R.string.draftProgressMessage), true); 
      } 
     }); 
+2

Tuve el mismo problema, y ​​solo ocurrió cuando abría un 'Dialog' /' ProcessDialog' cuando la actividad estaba en pausa. Es ese el caso? – Wroclai

+1

¿O puede estar cambiando de orientación? –

+0

Actualice la respuesta aceptada para que sea 'dismiss' – yonix

Respuesta

15

La fuga proviene probablemente de su atributo PixelRainActivity.staticThis. Si mantiene una referencia a una actividad, incluso después de que esta actividad se haya destruido, tiene una pérdida de memoria.

La forma más fácil de solucionarlo es usar la aplicación Context en su lugar. Cambiar su línea staticThis = this en el método onCreate()-staticThis = this.getApplicationContext() y debería funcionar (y cambiar el tipo de staticThis a Context si esto no es ya el caso)

+19

no funcionó para mí. Estoy usando progressDialog.show() en la tarea de Async onPreExecute(). y obtengo: android.view.WindowManager $ BadTokenException: no se puede agregar la ventana - token null no es para una aplicación – usman

+0

Si nada funciona, use try/catch para evitar que la aplicación se cuelgue. – usman

+14

Para crear Dialog, no debe pasar Contexto, sino Actividad. Por lo tanto, this.getApplicationContext() no es correcto –

1

En lugar de utilizar ProgressDialog.show(), trate de usar

Activity.showDialog() que debe administrar automáticamente el Dialog para usted y evitar fugas.

EDIT: Cuando se llama a showDialog(int), se disparará Activity.onCreateDialog(int) donde se puede crear el Dialog desea y devolver el Dialog que desea mostrar.

+1

, pero con Activity.showDialog() Necesito pasar una ID a un diálogo, ¿cómo mostrar el cuadro de diálogo de progreso? –

+11

Actualización: ¡Este método ahora se deprecia! – PravinDodia

2

Cygnus tiene una buena idea utilizar showDialog (MY_INT), donde MY_INT es solo un valor constante que elija para distinguirlo de cualquier otro diálogo similar que ejecute de esa manera. Lo toma de la misma manera con dismissDialog (MY_INT). Simplemente no lo ejecute desde su método onPause. Es posible que desee hacer eso en lugar del método onResume de la actividad a la que va el usuario. A continuación, se reemplaza el método onCreateDialog de que la actividad de la siguiente manera:

@Override 
protected Dialog onCreateDialog(int id) { 
    if(id == MY_INT) { 
     ProgressDialog progressDialog = new ProgressDialog(this); 
     progressDialog.setMessage("Your message string"); 
     return progressDialog; 
    } 
    return super.onCreateDialog(id); 
} 
101

Uso:

progressDialog.dismiss(); 

en el trabajo final

+0

POR FAVOR haga de esto la respuesta aceptada y ahorre todos nosotros el tiempo ... – yonix

0

Si usted está usando alguna thread o AsyncTask y descarga de material de Internet y mostrando progress bar, debe usar DialogFragment o cancelar el progreso dialog cuando Activity obtener detener también si está mostrando progreso en Asynctask puño cancelar Asynctask y anula oncancel método de devolución de llamada y dismiss diálogo de progreso allí.

Window leak en Activity o fragment es en realidad se produce debido a que está intentando agregar una ventana y al mismo tiempo se nota hasta que está en la foreground, pero cuando está pulsando la casa se pone en pausa y luego es detenido a través de la onStop () Por lo tanto, su CustomView permanece adherido a la ventana que ahora ha desaparecido. De acuerdo con el sistema, su customView ocupó el espacio que no soltó.

0

Es mejor utilizar un AsyncTask para obtener algo de internet en segundo plano. Y no hay necesidad de pasar un contexto estático sin embargo. Y la actividad

new YourAsyncTask(context).execute(); 

llamada AsyncTask como la de arriba

private class YourAsynTask extends AsyncTask<String,Void,String> 
{ 
private Context context; 
private ProgressDialog progressDialog; 

//pass context in constructor 
    public YourAsynTask(Context context) 
    { 
    this.context = context; 
    } 

    //show progress in onPre 
    @Override 
    protected void onPreExecute() 
    { 
    //show Progress code here. 
    progressDialog = ProgressDialog.show(context, "", "Loading. Please wait...", true); 
    } 

    //dismiss Progress dialog in onPost 
    @Override 
    protected void OnPostExecute(String response) 
    { 
    if(progressDialog!=null) 
    progressDialog.dismiss(); 
    progressDialog = null; 
    } 
} 
1

hay situaciones en las que hay que verificar en onDetach o en onDestroy si el diálogo de progreso es aún visible. Al igual que :

@Override 
public void onDetach() { 
    if (mProgressDialog != null && mProgressDialog.isShowing()) 
     mProgressDialog.dismiss(); 
    super.onDetach(); 
} 
0

intente llamar progressDialog.dismiss() antes de la actividad muere. Tengo el mío arreglado así.

Cuestiones relacionadas