Quelle est cette erreur et pourquoi cela se produit-il?
05-17 18:24:57.069: ERROR/WindowManager(18850): Activity com.mypkg.myP has leaked window com.Android.internal.policy.impl.PhoneWindow$DecorView@44c46ff0 that was originally added here
05-17 18:24:57.069: ERROR/WindowManager(18850): Android.view.WindowLeaked: Activity ccom.mypkg.myP has leaked window com.Android.internal.policy.impl.PhoneWindow$DecorView@44c46ff0 that was originally added here
05-17 18:24:57.069: ERROR/WindowManager(18850): at Android.view.ViewRoot.<init>(ViewRoot.Java:231)
05-17 18:24:57.069: ERROR/WindowManager(18850): at Android.view.WindowManagerImpl.addView(WindowManagerImpl.Java:148)
05-17 18:24:57.069: ERROR/WindowManager(18850): at Android.view.WindowManagerImpl.addView(WindowManagerImpl.Java:91)
05-17 18:24:57.069: ERROR/WindowManager(18850): at Android.view.Window$LocalWindowManager.addView(Window.Java:424)
05-17 18:24:57.069: ERROR/WindowManager(18850): at Android.app.Dialog.show(Dialog.Java:239)
05-17 18:24:57.069: ERROR/WindowManager(18850): at com.mypkg.myP$PreparePairingLinkageData.onPreExecute(viewP.Java:183)
05-17 18:24:57.069: ERROR/WindowManager(18850): at Android.os.AsyncTask.execute(AsyncTask.Java:391)
05-17 18:24:57.069: ERROR/WindowManager(18850): at com.mypkg.myP.onCreate(viewP.Java:94)
05-17 18:24:57.069: ERROR/WindowManager(18850): at Android.app.Instrumentation.callActivityOnCreate(Instrumentation.Java:1047)
05-17 18:24:57.069: ERROR/WindowManager(18850): at Android.app.ActivityThread.performLaunchActivity(ActivityThread.Java:2544)
05-17 18:24:57.069: ERROR/WindowManager(18850): at Android.app.ActivityThread.handleLaunchActivity(ActivityThread.Java:2621)
05-17 18:24:57.069: ERROR/WindowManager(18850): at Android.app.ActivityThread.access$2200(ActivityThread.Java:126)
05-17 18:24:57.069: ERROR/WindowManager(18850): at Android.app.ActivityThread$H.handleMessage(ActivityThread.Java:1932)
05-17 18:24:57.069: ERROR/WindowManager(18850): at Android.os.Handler.dispatchMessage(Handler.Java:99)
05-17 18:24:57.069: ERROR/WindowManager(18850): at Android.os.Looper.loop(Looper.Java:123)
05-17 18:24:57.069: ERROR/WindowManager(18850): at Android.app.ActivityThread.main(ActivityThread.Java:4595)
05-17 18:24:57.069: ERROR/WindowManager(18850): at Java.lang.reflect.Method.invokeNative(Native Method)
05-17 18:24:57.069: ERROR/WindowManager(18850): at Java.lang.reflect.Method.invoke(Method.Java:521)
05-17 18:24:57.069: ERROR/WindowManager(18850): at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:860)
05-17 18:24:57.069: ERROR/WindowManager(18850): at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:618)
05-17 18:24:57.069: ERROR/WindowManager(18850): at dalvik.system.NativeStart.main(Native Method)
Vous essayez d'afficher un dialogue après avoir terminé une activité.
[MODIFIER]
Cette question est l’une des recherches les plus fréquentes sur Google pour les développeurs Android, Par conséquent, il convient d’ajouter quelques points importants à partir des commentaires, ce qui pourrait être plus utile pour les futurs enquêteurs sans approfondir la conversation de commentaires.
Réponse 1 :
Vous essayez d'afficher un dialogue après avoir terminé une activité.
Réponse 2
Cette erreur peut être un peu trompeuse dans certaines circonstances (bien que La réponse soit toujours tout à fait exacte) - c’est-à-dire dans mon cas un Une exception non gérée a été lancée dans une tâche asynchrone, ce qui a provoqué le L'activité s'est arrêtée, puis un journal de progrès ouvert a provoqué ceci Exception .. si la "vraie" exception était un peu plus tôt dans le journal
Réponse 3
Appelez rejeter () sur l'instance de dialogue créée avant de quitter votre Activité, par exemple dans onPause () ou onDestroy ()
La solution consiste à appeler dismiss()
sur la Dialog
que vous avez créée dans viewP.Java:183
avant de quitter la Activity
, par exemple. dans onPause()
. Tous les Window
s & Dialog
s doivent être fermés avant de laisser un Activity
.
Si vous utilisez AsyncTask
, ce message de journal peut être trompeur. Si vous regardez dans votre journal, vous pouvez trouver une autre erreur, probablement une dans votre méthode doInBackground()
de votre AsyncTask
, qui fait exploser votre Activity
courante, et donc une fois que la AsyncTask
revient .. eh bien, vous connaissez le reste. Certains autres utilisateurs ont déjà expliqué cela ici :-)
J'ai déclenché cette erreur en appelant par erreur hide()
au lieu de dismiss()
sur AlertDialog
.
Vous pouvez obtenir cette exception par une simple erreur, par exemple en appelant accidentellement finish()
après avoir affiché une AlertDialog
, si vous manquez une instruction de rupture d'appel dans une instruction switch ...
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.new_button:
openMyAlertDialog();
break; <-- If you forget this the finish() method below
will be called while the dialog is showing!
case R.id.exit_button:
finish();
break;
}
}
La méthode finish()
ferme la Activity
, mais la AlertDialog
continue de s'afficher!
Ainsi, lorsque vous observez attentivement le code, recherchez les problèmes de filetage ou les codages complexes et autres, ne perdez pas de vue la forêt pour les arbres. Parfois, cela peut être simplement quelque chose d'aussi simple et stupide qu'une déclaration de rupture manquante. :)
Ce problème survient lorsque vous essayez d'afficher un dialogue après avoir quitté une activité.
Je viens de résoudre ce problème simplement en écrivant le code suivant:
@Override
public void onDestroy(){
super.onDestroy();
if ( progressDialog!=null && progressDialog.isShowing() ){
progressDialog.cancel();
}
}
En gros, à partir de quelle classe vous avez commencé progressDialog, substituez la méthode onDestroy et procédez ainsi. Il a résolu le problème "L'activité a une fenêtre qui fuit".
Les réponses à cette question étaient toutes correctes, mais un peu déroutant pour moi de comprendre pourquoi. Après avoir joué environ 2 heures, la raison de cette erreur (dans mon cas) m’a frappé:
En lisant d’autres réponses, vous savez déjà que l’erreur X has leaked window DecorView@d9e6131[]
signifie qu’une boîte de dialogue était ouverte à la fermeture de votre application. Mais pourquoi?
Il se peut que votre application se soit bloquée pour une autre raison alors que votre boîte de dialogue était ouverte
Cela a entraîné la fermeture de votre application en raison d'un bogue dans votre code, qui a pour conséquence que la boîte de dialogue reste ouverte en même temps que votre application a été fermée en raison de l'autre erreur.
Alors, regarde à travers ta logique. Résoudre la première erreur, puis la deuxième erreur se résoudra elle-même
Une erreur en provoque une autre, ce qui en provoque une autre, comme DOMINOS!
J'ai récemment fait face au même problème.
La raison derrière ce problème est que l'activité étant fermée avant que la boîte de dialogue ne soit fermée. Il y a diverses raisons pour que cela se produise. Ceux mentionnés dans les messages ci-dessus sont également corrects.
Je me suis retrouvé dans une situation, car dans le fil de discussion, j'appelais une fonction qui lançait une exception. Pour cette raison, la fenêtre a été fermée et par conséquent l'exception.
Fermer le dialogue lorsque l'activité détruit
@Override
protected void onDestroy()
{
super.onDestroy();
if (pDialog!=null && pDialog.isShowing()){
pDialog.dismiss();
}
}
Cela pourrait aider.
if (! isFinishing()) {
dialog.show();
}
J'ai eu le même message d'erreur obscure et je n'avais aucune idée pourquoi. Étant donné les indices des réponses précédentes, j'ai remplacé mes appels non-graphiques par mDialog.finish () par mDialog.dismiss () et les erreurs ont disparu. Cela n'affectait pas le comportement de mon widget, mais il était déconcertant et aurait très bien pu signaler une fuite de mémoire importante.
Je recevais ces journaux dans mon application de lecteur vidéo. Ces messages ont été lancés alors que le lecteur vidéo était fermé. Fait intéressant, j'avais l'habitude d'obtenir ces journaux une fois dans quelques exécutions de manière aléatoire. De plus, ma demande ne comporte aucune progressdialog
. Enfin, j'ai contourné ce problème avec la mise en œuvre ci-dessous.
@Override
protected void onPause()
{
Log.v("MediaVideo", "onPause");
super.onPause();
this.mVideoView.pause();
this.mVideoView.setVisibility(View.GONE);
}
@Override
protected void onDestroy()
{
Log.v("MediaVideo", "onDestroy");
super.onDestroy();
}
@Override
protected void onResume()
{
Log.v("MediaVideo", "onResume");
super.onResume();
this.mVideoView.resume();
}
Remplacez la OnPause
par l'appel à mVideoView.pause()
et l'ensemble visibility
à GONE
. De cette façon, je pourrais résoudre le problème d'erreur de journal "Activity has leaked window
".
J'avais le même problème et j'ai trouvé cette page. Bien que ma situation soit différente, j'ai appelé finish
à partir d'un bloc if
avant que celui-ci ne définisse le champ d'alerte.
Donc, simplement appeler dismiss
ne fonctionnerait pas (comme cela n'a pas encore été fait) mais après avoir lu Alex Volovoy answer et réalisé que c'était la boîte d'alerte qui le provoquait. J'ai essayé d'ajouter une instruction return juste après l'arrivée dans ce bloc if
et cela a résolu le problème.
J'ai pensé qu'une fois que vous avez appelé terminer, tout a été arrêté et terminé, mais ce n'est pas le cas. Il semble aller à la fin du bloc de code dans lequel il se termine puis se termine.
Donc, si vous voulez implémenter une situation où parfois il faut finir avant de faire du code, vous devez mettre une déclaration return juste après l'arrivée ou il va continuer et agir comme si l'arrivée avait été appelée à la fin du processus. bloc de code pas où vous l'avez appelé. C'est pourquoi j'ai eu toutes ces erreurs étranges.
private picked(File aDirectory){
if(aDirectory.length()==0){
setResult(RESULT_CANCELED, new Intent());
finish();
return;
}
AlertDialog.Builder alert= new AlertDialog.Builder(this); // Start dialog builder
alert
.setTitle("Question")
.setMessage("Do you want to open that file?"+aDirectory.getName());
alert
.setPositiveButton("OK", okButtonListener)
.setNegativeButton("Cancel", cancelButtonListener);
alert.show();
}
Si vous ne placez pas le retour juste après que j'ai appelé finish, cela agira comme si vous l'aviez appelée après la fonction alert.show();
et par conséquent, cela indiquerait que la fenêtre fuit en terminant juste après que vous ayez fait apparaître la boîte de dialogue ce n'est pas le cas, il pense toujours que c'est le cas.
Je pensais que j'ajouterais ceci comme ici car cela montre que la commande d'arrivée a agi différemment, alors je pensais que c'était le cas et je suppose qu'il y a d'autres personnes qui pensent la même chose que moi avant de découvrir cela.
Ce n'est pas la réponse à la question mais c'est pertinent pour le sujet.
Si l'activité a défini un attribut dans le manifeste
Android:noHistory="true"
ensuite, après l'exécution de onPause (), le contexte d'activité est perdu. Donc, toute la vue utilisant this context peut donner cette erreur.
Essayez non seulement d'afficher une alerte, mais vous pouvez également l'invoquer lorsque vous terminez une instance d'activité particulière et essayez de démarrer une nouvelle activité/un nouveau service ou d'essayer de l'arrêter.
Exemple:
OldActivity instance;
oncreate() {
instance=this;
}
instance.finish();
instance.startActivity(new Intent(ACTION_MAIN).setClass(instance, NewActivity.class));
Essayez ce code:
public class Sample extends Activity(){
@Override
public void onCreate(Bundle instance){
}
@Override
public void onStop() {
super.onStop();
progressdialog.dismiss(); // try this
}
}
Avait le problème où j'ai fini une activité quand un ProgressDialog était encore montré.
Donc, commencez par masquer le dialogue, puis terminez l'activité.
Cela m'est arrivé lorsque j'utilise ProgressDialog
dans AsyncTask
. En fait, j'utilise la méthode hide()
dans onPostExecute
. Sur la base de la réponse de @Alex Volovoy, je dois utiliser dismiss()
avec ProgressDialog
pour le supprimer dans onPostExecute.
progressDialog.hide(); // Don't use it, it gives error
progressDialog.dismiss(); // Use it
L'erreur "Activity has leaked window that was originally added...
" se produit lorsque vous essayez d'afficher une alerte après que la Activity
soit effectivement finished
.
Vous avez deux options, autant que je sache:
dismiss()
sur la dialog
avant de quitter votre activité.dialog
dans un autre thread et exécutez-la sur cette thread
(indépendante de la activity
actuelle).Cela peut être le cas si vous avez une erreur dans la fonction doInBackground()
et que vous avez ce code.
Essayez d'ajouter un dialogue enfin. Au premier contrôle et correction de la fonction doInBackground()
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(CreateAccount.this);
pDialog.setMessage("Creating Product..");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
protected String doInBackground(String...args) {
ERROR CAN BE IS HERE
}
protected void onPostExecute(String file_url) {
// dismiss the dialog once done
pDialog.dismiss();
Généralement, ce problème survient en raison d'une boîte de dialogue de progression: vous pouvez résoudre ce problème en appliquant l'une des méthodes suivantes dans votre activité:
// 1):
@Override
protected void onPause() {
super.onPause();
if ( yourProgressDialog!=null && yourProgressDialog.isShowing() )
{
yourProgressDialog.cancel();
}
}
// 2) :
@Override
protected void onDestroy() {
super.onDestroy();
if ( yourProgressDialog!=null && yourProgressDialog.isShowing()
{
yourProgressDialog.cancel();
}
}
Vous devez créer un objet Progressdialog
dans la méthode onPreExecute
de AsyncTask
et vous devez dismiss
sur la méthode onPostExecute
.
La meilleure solution consiste simplement à ajouter une boîte de dialogue dans la boîte de dialogue tentative d'arrêt et de fermeture en cas d'exception
Il suffit d'utiliser le code ci-dessous
try {
dialog.show();
} catch (Exception e) {
dialog.dismiss();
}
Dans mon cas, la raison était que j'avais oublié d'inclure une permission dans le fichier manifeste Android.
Comment ai-je découvert? Eh bien, tout comme @Bobby dit dans un commentaire situé sous la réponse acceptée, il suffit de faire défiler davantage vos journaux pour afficher la première raison ou l'événement qui a réellement déclenché l'exception. Apparemment, le message "L'activité a été divulguée par la fenêtre qui a été ajoutée à l'origine" est uniquement une exception résultant de la première exception.
Essayez le code ci-dessous, il fonctionnera à tout moment si vous voulez fermer le dialogue de progression et voir si son instance est disponible ou non.
try {
if (null != progressDialog && progressDialog.isShowing()) {
progressDialog.dismiss();
progressDialog = null;
}
} catch (Exception e) {
e.printStackTrace();
}
Les exceptions de fenêtres qui fuient ont deux raisons:
1) afficher la boîte de dialogue lorsque le contexte d'activité n'existe pas, pour résoudre ce problème, vous devez afficher la boîte de dialogue uniquement si vous êtes certain que l'activité existe:
if(getActivity()!= null && !getActivity().isFinishing()){
Dialog.show();
}
2) ne ferme pas le dialogue de manière appropriée, pour résoudre utiliser ce code:
@Override
public void onDestroy(){
super.onDestroy();
if ( Dialog!=null && Dialog.isShowing() ){
Dialog.dismiss();
}
}
La meilleure solution est celle-ci avant d'afficher progressbar
ou progressDialog
if (getApplicationContext().getWindow().getDecorView().isShown()) {
//Show Your Progress Dialog
}
Assurez-vous simplement que votre activité ne se ferme pas de manière inattendue en raison de quelques exceptions soulevées quelque part dans votre code. Généralement, cela se produit dans une tâche asynchrone lorsque l'activité est confrontée à une fermeture forcée de la méthode doinBackground, puis que asynctask renvoie à la méthode onPostexecute.
Selon moi, le problème est que vous essayez d'appeler une boîte de dialogue juste après la fin d'une activité. Par conséquent, selon moi, vous pouvez donner un peu de retard à l'aide de Handler et votre problème sera résolu, par exemple:
Handler handler=new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
dialog.show();
//or
dialog.dismiss();
}
},100);
if (mActivity != null && !mActivity.isFinishing() && mProgressDialog != null && mProgressDialog.isShowing()) {
mProgressDialog.dismiss();
}
Vous avez cette erreur lorsque vous essayez d'afficher un pain grillé à partir du fil d'arrière-plan . Il a été résolu en exécutant le code associé à l'interface utilisateur sur le fil d'interface utilisateur
J'ai le même genre de problème. l'erreur n'était pas dans la Dialog
mais dans une EditText
. J'essayais de changer la valeur de Edittext
à l'intérieur d'un Assynctask
. le seul problème que je pouvais résoudre était de créer une nouvelle runnable
.
runOnUiThread(new Runnable(){
@Override
public void run() {
...
}
});
J'ai une autre solution pour cela, et j'aimerais savoir si cela vous semble valable: au lieu de rejeter dans onDestroy, qui semble être la solution principale, j'étends ProgressDialog ...
public class MyProgressDialog extends ProgressDialog {
private boolean isDismissed;
public MyProgressDialog(Context context) {
super(context);
}
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
dismiss();
}
@Override
public void dismiss() {
if (isDismissed) {
return;
}
try {
super.dismiss();
} catch (IllegalArgumentException e) {
// ignore
}
isDismissed = true;
}
C’est préférable, AFAIC, car il n’est pas nécessaire de tenir la boîte de dialogue de progression en tant que membre, il suffit de déclencher (afficher) et d’oublier
Assurez-vous d'appeler this.dialog.show. (Activité)
Je rencontre également le problème WindowLeaked lors de l'exécution du test Monkey. Le logcat est ci-dessous.
Android.support.v7.app.AppCompatDelegateImplV7$ListMenuDecorView@4334fd40 that was originally added here
Android.view.WindowLeaked: Activity com.myapp.MyActivity has leaked window Android.support.v7.app.AppCompatDelegateImplV7$ListMenuDecorView@4334fd40 that was originally added here
at Android.view.ViewRootImpl.<init>(ViewRootImpl.Java:409)
at Android.view.WindowManagerImpl.addView(WindowManagerImpl.Java:312)
at Android.view.WindowManagerImpl.addView(WindowManagerImpl.Java:224)
at Android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.Java:149)
at Android.view.Window$LocalWindowManager.addView(Window.Java:554)
at Android.support.v7.app.AppCompatDelegateImplV7.openPanel(AppCompatDelegateImplV7.Java:1150)
at Android.support.v7.app.AppCompatDelegateImplV7.onKeyUpPanel(AppCompatDelegateImplV7.Java:1469)
at Android.support.v7.app.AppCompatDelegateImplV7.onKeyUp(AppCompatDelegateImplV7.Java:919)
at Android.support.v7.app.AppCompatDelegateImplV7.dispatchKeyEvent(AppCompatDelegateImplV7.Java:913)
at Android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.dispatchKeyEvent(AppCompatDelegateImplBase.Java:241)
at com.Android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.Java:2009)
at Android.view.ViewRootImpl.deliverKeyEventPostIme(ViewRootImpl.Java:3929)
at Android.view.ViewRootImpl.deliverKeyEvent(ViewRootImpl.Java:3863)
at Android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.Java:3420)
at Android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.Java:4528)
at Android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.Java:4506)
at Android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.Java:4610)
at Android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.Java:171)
at Android.os.MessageQueue.nativePollOnce(Native Method)
at Android.os.MessageQueue.next(MessageQueue.Java:125)
at Android.os.Looper.loop(Looper.Java:124)
at Android.app.ActivityThread.main(ActivityThread.Java:4898)
at Java.lang.reflect.Method.invokeNative(Native Method)
at Java.lang.reflect.Method.invoke(Method.Java:511)
at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:1008)
at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:775)
at dalvik.system.NativeStart.main(Native Method)
Mon activité est AppCompatActivity.Et je l'ai réinsérée avec le code ci-dessous dans l'activité.
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
// added by sunhang : intercept menu key to resove a WindowLeaked error in monkey-test.
if (event.getKeyCode() == KeyEvent.KEYCODE_MENU) {
return true;
}
return super.dispatchKeyEvent(event);
}
Si vous utilisez LiveData, essayez de faire liveData.postValue(someValue)
lorsque vous mettez à jour la valeur plutôt que d'utiliser liveData.value = someValue
J'utilisais le dialogue `onError d'un lecteur vidéo et au lieu de devenir fou (j'ai testé toutes ces solutions)
J'ai opté pour DialogFragment
http://developer.Android.com/reference/Android/app/DialogFragment.html .
Vous pouvez renvoyer la création de générateur dans une classe DialogFragment
intérieure, il suffit de remplacer onCreateDialog
Peut-être avez-vous utilisé findViewById
en activité au lieu de dialog.findViewById
et défini ensuite une OnClickListener
sur une instance null
et qui a probablement causé l'erreur initiale.
J'ai également été confronté à ce problème pendant un certain temps, mais j'ai réalisé que ce n'est pas à cause de dialog
dans mon cas, c'est à cause de ActionMode
. Donc, si vous essayez de terminer l’activité quand une ActionMode
est ouverte, cela posera ce problème. Dans la variable onPause
de votre activité, terminez le mode action.
private ActionMode actionMode;
@Override
public void onActionModeStarted(ActionMode mode) {
super.onActionModeStarted(mode);
actionMode = mode;
}
@Override
protected void onPause() {
super.onPause();
if (actionMode != null) actionMode.finish();
}