Boîte de dialogue lancer "Impossible d'ajouter de la fenêtre — jeton de la valeur null n'est pas une application” avec getApplication() dans le contexte de la
Mon Activité est d'essayer de créer un AlertDialog qui nécessite un Contexte en tant que paramètre. Cela fonctionne comme prévu si j'utilise:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
Cependant, je suis réticent à l'idée de l'utilisation de "ce" en tant que contexte, en raison du risque de fuites de mémoire lorsque l'Activité est détruit et recréé même au cours de quelque chose de simple comme une rotation de l'écran. À partir d'un related post sur l'Android developer blog:
Il y a deux façons simples pour éviter de contexte liés à des fuites de mémoire. Le plus évident est d'éviter d'échapper au contexte, à l'extérieur de son propre champ. L'exemple ci-dessus a montré le cas de référence statique mais intérieur des classes et de leur référence implicite à l'extérieur de la classe peuvent être tout aussi dangereux. La deuxième solution est d'utiliser le contexte de l'Application. Ce contexte va vivre aussi longtemps que votre application est en vie et ne dépend pas de la activités du cycle de vie. Si vous avez l'intention de les garder à long terme des objets qui ont besoin d'un contexte, rappelez-vous l'objet application. Vous pouvez l'obtenir facilement en appelant le Contexte.getcontexteapplication() ou de l'Activité.getApplication().
Mais pour le AlertDialog()
ni getApplicationContext()
ou getApplication()
est acceptable en tant que Contexte, qu'il lève l'exception:
"Impossible d'ajouter la fenêtre du jeton de la valeur null n'est pas pour une application”
par les références: Un, Deux, Trois, etc.
Alors, faut-il vraiment être considéré comme un "bug", puisque nous sommes officiellement conseillé d'utiliser Activity.getApplication()
et pourtant, il ne fonctionne pas comme annoncé?
Jim
- de référence pour le premier article où R. Guy conseille d'utiliser getApplication: android-developers.blogspot.com/2009/01/...
- autres références: stackoverflow.com/questions/1561803/...
- autre référence:stackoverflow.com/questions/2634991/...
- groups.google.com/group/android-developers/browse_thread/thread/...
- Connexes: Android 1.6: "android.vue.WindowManager$BadTokenException: Impossible d'ajouter de la fenêtre -- jeton null n'est pas pour une application"
- C'est une question intéressante. Je voudrais quelqu'un de répondre à votre question; Donc, cela doit-il vraiment être considéré comme un "bug", puisque nous sommes officiellement conseillé d'utiliser de l'Activité.getApplication() et pourtant il ne fonctionne pas comme annoncé?
- Double Possible de Android "Impossible d'ajouter la fenêtre -- jeton null n'est pas pour une demande d' " exception
Vous devez vous connecter pour publier un commentaire.
Au lieu de
getApplicationContext()
, il suffit d'utiliserActivityName.this
.Listener
classes sont souvent anonymes-intérieure, j'ai tendance à faire justefinal Context ctx = this;
et je suis loin 😉yourActivity.this
si vous sont utilisés en fonction dethis
à l'échelle mondiale". Le stockage d'unActivity
contexte (qui est ce quethis
est fait référence dans ce cas) dans unstatic
champ est un grand no-no comme son vraiment facile à une fuite de mémoire. @Artems approche de la "ExternalClassName.this
" est très certainement la bonne.getApplicationContext()
donne sans doute l'erreur due à une boîte de dialogue qui ont besoin d'être attaché à laActivity
contexte, par opposition à laApplication
contexte...Context
la classe, surtout queActivity
etApplication
à la fois d'étendre contexte, mais ont différentes extérieure de l'état et pas dans toutes les situations et donc substituables les uns les autres, qui va à l'encontre de la L de SOLID de la programmation orientée objet principes de conception et conduit donc à confusion comme la Fpo question.Fragment
, utilisezgetActivity()
.ActivityName
dansPreferenceFragment
?À l'aide de
this
ne fonctionne pas pour moi, maisMyActivityName.this
fait. Espérons que cela aide quelqu'un qui pourrait ne pas obtenirthis
de travail.this
de l'intérieur d'un intérieur de classe. Si vous souhaitez faire référence à l'instance de l'extérieur de la classe, vous devez l'indiquer, comme vous le faites avecOuterClass.this
. Juste à l'aide dethis
toujours les références les plus à l'intérieur de la classe de l'instance.Vous pouvez continuer à utiliser
getApplicationContext()
, mais avant de l'utiliser, vous devez ajouter ce drapeau:dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)
, et l'erreur ne s'affichera pas.Ajouter de l'autorisation suivante à votre manifeste:
Votre boîte de dialogue ne devrait pas être une longue durée de vie de l'objet qui a besoin d'un cadre". La documentation est source de confusion. En gros, si vous faites quelque chose comme:
(note de l' statique)
Puis dans une activité, quelque part, vous ne
Vous auriez probablement une fuite de l'activité d'origine au cours d'une rotation ou similaire qui permettrait de détruire l'activité. (À moins que vous nettoyer en onDestroy, mais dans ce cas, vous ne serait probablement pas faire l'objet de Dialogue statique)
Pour certaines structures de données, il serait logique de les rendre statique et en fonction de la demande du contexte, mais généralement pas pour l'INTERFACE utilisateur de choses se rapportant, comme les boîtes de dialogue. Donc quelque chose comme ceci:
Est fine et ne doit pas la fuite de l'activité de mDialog serait libéré avec l'activité, car elle n'est pas statique.
Vous avez correctement identifié le problème, quand vous avez dit "... pour l'AlertDialog() ni getcontexteapplication() ou getApplication() est acceptable en tant que Contexte, qu'il lève l'exception: "Impossible d'ajouter la fenêtre du jeton de la valeur null n'est pas une application""
Pour créer une boîte de Dialogue, vous avez besoin d'un Contexte d'Activité ou un Contexte de Service, pas un le Contexte de l'Application (les deux getcontexteapplication() et getApplication() renvoient un Contexte d'Application).
Voici comment vous obtenez le Contexte d'Activité:
(1) à une Activité ou À un Service:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
(2) Dans un Fragment:
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
Fuites de mémoire n'est pas un problème qui est intrinsèque à la "ce" de référence, qui est une référence de l'objet à lui-même (c'est à dire le renvoi à la mémoire allouée pour stocker les données de l'objet). Il arrive à tout mémoire allouée pour qui le Garbage Collector (GC) est incapable de se libérer après la mémoire allouée a atteint la fin de sa durée utile.
La plupart du temps, quand une variable est hors de portée, la mémoire sera récupérée par le GC. Cependant, des fuites de mémoire peut se produire lorsque la référence à un objet tenu par une variable, par exemple "x", persiste même après que l'objet a atteint la fin de sa durée utile. La mémoire allouée sera donc perdu tant que "x" contient une référence car GC ne libérer de la mémoire tant que la mémoire est encore référencée. Parfois, des fuites de mémoire ne sont pas visibles en raison de une chaîne de références de la mémoire allouée. Dans un tel cas, le GC ne libère pas la mémoire jusqu'à ce que toutes les références à ce mémoire ont été supprimés.
Pour empêcher les fuites de mémoire, vérifiez votre code pour les erreurs de logiques qui causent la mémoire allouée à être référencé indéfiniment par "ce" (ou d'autres références). N'oubliez pas de vérifier la chaîne de références ainsi. Voici quelques outils que vous pouvez utiliser pour vous aider à analyser l'utilisation de la mémoire et de trouver ces satanés fuites de mémoire:
JRockit De Contrôle De Mission
JProbe
YourKit
AD4J
J'ai dû envoyer mon contexte par le biais d'un constructeur sur un adaptateur personnalisé affiché dans un fragment et eu ce problème avec getcontexteapplication(). Je l'ai résolu avec:
this.getActivity().getWindow().getContext()
dans les fragmentsonCreate
de rappel.dans Activité suffit d'utiliser:
dans Fragment:
Dans
Activity
sur le clic du bouton affichant une boîte de dialogueA fonctionné pour moi.
Petit hack: vous pouvez éviter de détruire votre activité par GC (vous ne devriez pas le faire, mais il peut aider dans certaines situations. N'oubliez pas de mettre
contextForDialog
ànull
lorsqu'il n'est plus nécessaire):***** kotlin version *****
Vous devez passer
this@YourActivity
au lieu deapplicationContext
oubaseContext
Si vous utilisez un fragment et à l'aide de AlertDialog/Toast message, puis utiliser getActivity() dans le paramètre de contexte.
comme ce
ajoutant
et
"android.permission.SYSTEM_ALERT_WINDOW"/>
dans le manifesteIl fonctionne pour moi maintenant. Après même fermer et ouvrir l'application, m'a donné l'erreur à l'époque.
J'ai été en utilisant
ProgressDialog
dans un fragment et a été l'obtention de cette erreur sur le passagegetActivity().getApplicationContext()
que le paramètre du constructeur. Changer l'getActivity().getBaseContext()
ne fonctionne pas non plus.La solution qui a fonctionné pour moi a été de passer
getActivity()
; c'est à direprogressDialog = new ProgressDialog(getActivity());
Utilisation
MyDialog md = new MyDialog(MyActivity.this.getParent());
Si vous êtes en dehors de l'Activité, alors vous devez utiliser dans votre fonction "NameOfMyActivity.ce" comme une Activité une activité, par exemple:
Si vous utilisez un fragment et à l'aide d'un
AlertDialog /Toast
message, utilisezgetActivity()
dans le paramètre de contexte.A fonctionné pour moi.
Cheers!
Essayez d'utiliser le contexte d'une activité qui sera sous la boîte de dialogue. Mais soyez prudent lorsque vous utilisez le mot clé "this", car il ne fonctionnera pas à chaque fois.
Par exemple, si vous avez TabActivity comme hôte avec deux onglets, et chaque onglet est une autre activité, et si vous essayez de créer une boîte de dialogue à partir de l'un des onglets (activités) et si vous utilisez "ce", puis vous obtiendrez d'exception,
Dans ce cas la boîte de dialogue doit être connecté à l'hôte de l'activité de l'accueil de tout et visible. (vous pouvez dire que la plupart des parent visible l'Activité du contexte)
Je n'ai pas trouvé cette info dans un document, mais en essayant. C'est ma solution sans fond fort, Si quelqu'un avec une meilleure knownledge, n'hésitez pas à commenter.
Pour les futurs lecteurs, cela devrait vous aider:
Dans mon cas de travail:
Ou une autre possibilité est de créer une boîte de Dialogue comme suit:
Je pense qu'il peut arriver si vous essayez d'afficher une boîte de dialogue à partir d'un thread qui n'est pas le principal thread d'INTERFACE utilisateur.
Utilisation
runOnUiThread()
dans ce cas.Essayer
getParent()
à l'argument de la place de contexte comme celui de la nouvelleAlertDialog.Builder(getParent());
Espère que cela va fonctionner, il a travaillé pour moi.Après avoir pris un coup d'oeil à l'API, vous pouvez passer à la boîte de dialogue de votre activité ou de getActivity si vous êtes dans un fragment, puis avec force les nettoyer avec dialogue.rejeter() dans le retour des méthodes pour éviter les fuites.
Si elle n'est pas explicitement indiqué nulle part que je sais, il semble que vous êtes passé en arrière de la boîte de dialogue dans le OnClickHandlers juste pour ce faire.