Mon activité tente de créer un AlertDialog qui nécessite un contexte comme paramètre. Cela fonctionne comme prévu si j'utilise:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
Cependant, je me méfie d'utiliser "this" comme contexte en raison du potentiel de fuites de mémoire lorsque Activity est détruit et recréé même pendant quelque chose de simple comme une rotation d'écran. À partir d'un article connexe sur le blog du développeur Android :
Il existe deux moyens simples d'éviter les fuites de mémoire liées au contexte. La plus évidente est d'éviter d'échapper au contexte en dehors de sa propre portée. L'exemple ci-dessus montre le cas d'une référence statique mais les classes internes et leur référence implicite à la classe externe peuvent être tout aussi dangereuses. La deuxième solution consiste à utiliser le contexte d'application. Ce contexte vivra tant que votre application sera en vie et ne dépendra pas du cycle de vie des activités. Si vous prévoyez de conserver des objets à longue durée de vie qui ont besoin d'un contexte, n'oubliez pas l'objet d'application. Vous pouvez l'obtenir facilement en appelant Context.getApplicationContext () ou Activity.getApplication ().
Mais pour le AlertDialog()
ni getApplicationContext()
ou getApplication()
est acceptable comme contexte, car il lève l'exception:
"Impossible d'ajouter une fenêtre - le token null n'est pas pour une application"
par références: 1 , 2 , 3 , etc.
Donc, cela devrait-il vraiment être considéré comme un "bug", car il est officiellement conseillé de l'utiliser Activity.getApplication()
et pourtant il ne fonctionne pas comme annoncé?
Jim
Réponses:
Au lieu de
getApplicationContext()
, utilisez simplementActivityName.this
.la source
Listener
cours sont souvent anonymes, j'ai tendance à le fairefinal Context ctx = this;
et je suis absent;)L'utilisation
this
n'a pas fonctionné pour moi, mais l'aMyActivityName.this
fait. J'espère que cela aide toute personne qui n'a pas pu se rendrethis
au travail.la source
this
de l'intérieur d'une classe interne. Si vous souhaitez référencer l'instance d'une classe externe, vous devez le spécifier, comme vous le faites avecOuterClass.this
. Utiliser simplement faitthis
toujours référence à l'instance la plus interne de la classe.Vous pouvez continuer à utiliser
getApplicationContext()
, mais avant utilisation, vous devez ajouter cet indicateur:,dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)
et l'erreur ne s'affichera pas.Ajoutez l'autorisation suivante à votre manifeste:
la source
Vous avez correctement identifié le problème lorsque vous avez dit "... pour AlertDialog () ni getApplicationContext () ni getApplication () n'est acceptable en tant que contexte, car il lève l'exception:" Impossible d'ajouter une fenêtre - le token null n'est pas pour une application'"
Pour créer une boîte de dialogue, vous avez besoin d'un contexte d'activité ou d'un contexte de service , pas d'un contexte d'application (les deux getApplicationContext () et getApplication () renvoient un contexte d'application).
Voici comment vous obtenez le contexte d'activité :
(1) Dans une activité ou un service:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
(2) Dans un fragment:
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
Les fuites de mémoire ne sont pas un problème intrinsèque à la référence "this", qui est la référence d'un objet à lui-même (c'est-à-dire la référence à la mémoire réellement allouée pour stocker les données de l'objet). Cela arrive à toute mémoire allouée pour laquelle le garbage collector (GC) est incapable de libérer une fois que la mémoire allouée a dépassé sa durée de vie utile.
La plupart du temps, lorsqu'une variable sort de la portée, la mémoire est récupérée par le GC. Cependant, des fuites de mémoire peuvent se produire lorsque la référence à un objet détenu par une variable, par exemple "x", persiste même après que l'objet a survécu à sa durée de vie utile. La mémoire allouée sera donc perdue aussi longtemps que "x" y fera référence car GC ne libérera pas la mémoire tant que cette mémoire sera toujours référencée. Parfois, les fuites de mémoire ne sont pas apparentes en raison d' une chaîne de références à la mémoire allouée. Dans un tel cas, le GC ne libérera pas la mémoire tant que toutes les références à cette mémoire n'auront pas été supprimées.
Pour éviter les fuites de mémoire, recherchez dans votre code des erreurs logiques qui provoquent un référencement indéfini de la mémoire allouée par «ceci» (ou d'autres références). N'oubliez pas de vérifier également les références de chaîne. Voici quelques outils que vous pouvez utiliser pour vous aider à analyser l'utilisation de la mémoire et à trouver ces fuites de mémoire embêtantes:
JRockit Mission Control
JProbe
YourKit
AD4J
la source
Votre dialogue ne doit pas être un "objet à longue durée de vie qui a besoin d'un contexte". La documentation est déroutante. Fondamentalement, si vous faites quelque chose comme:
(notez le statique )
Ensuite, dans une activité quelque part que vous avez fait
Vous feriez probablement fuir l'activité d'origine lors d'une rotation ou similaire qui détruirait l'activité. (À moins que vous ne nettoyiez dans onDestroy, mais dans ce cas, vous ne rendriez probablement pas l'objet Dialog statique)
Pour certaines structures de données, il serait logique de les rendre statiques et basées sur le contexte de l'application, mais généralement pas pour les choses liées à l'interface utilisateur, comme les boîtes de dialogue. Donc quelque chose comme ça:
Est bien et ne devrait pas fuir l'activité car mDialog serait libéré avec l'activité car elle n'est pas statique.
la source
J'ai dû envoyer mon contexte via un constructeur sur un adaptateur personnalisé affiché dans un fragment et j'ai eu ce problème avec getApplicationContext (). Je l'ai résolu avec:
this.getActivity().getWindow().getContext()
dans leonCreate
rappel des fragments .la source
dans l' activité, utilisez simplement:
en fragment:
la source
En
Activity
cliquant sur le bouton affichant une boîte de dialogueA travaillé pour moi.
la source
***** version kotlin *****
Vous devez passer
this@YourActivity
au lieu deapplicationContext
oubaseContext
la source
Petit hack: vous pouvez empêcher de détruire votre activité par GC (vous ne devriez pas le faire, mais il peut aider dans certaines situations Ne pas oublier de mettre.
contextForDialog
Ànull
quand il est plus nécessaire):la source
Si vous utilisez un fragment et utilisez le message AlertDialog / Toast, utilisez getActivity () dans le paramètre context.
comme ça
la source
Utilisez simplement ce qui suit:
POUR LES UTILISATEURS DE JAVA
Si vous utilisez l'activité ->
AlertDialog.Builder builder = new AlertDialog.Builder(this);
OU
AlertDialog.Builder builder = new AlertDialog.Builder(your_activity.this);
Si vous utilisez un fragment ->
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
POUR LES UTILISATEURS DE KOTLIN
Si vous utilisez l'activité ->
val builder = AlertDialog.Builder(this)
OU
val builder = AlertDialog.Builder(this@your_activity.this)
Si vous utilisez un fragment ->
val builder = AlertDialog.Builder(activity!!)
la source
ajouter
et
"android.permission.SYSTEM_ALERT_WINDOW"/>
en manifesteÇa marche pour moi maintenant. Après même fermer et ouvrir l'application, m'a donné l'erreur à ce moment-là.
la source
J'utilisais
ProgressDialog
dans un fragment et obtenais cette erreur en passantgetActivity().getApplicationContext()
comme paramètre constructeur. Le changer engetActivity().getBaseContext()
n'a pas fonctionné non plus.La solution qui a fonctionné pour moi était de passer
getActivity()
; c'est à direprogressDialog = new ProgressDialog(getActivity());
la source
Utilisation
MyDialog md = new MyDialog(MyActivity.this.getParent());
la source
Si vous êtes en dehors de l'activité, vous devez utiliser dans votre fonction "NameOfMyActivity.this" comme activité d'activité, par exemple:
la source
Si vous utilisez un fragment et utilisez un
AlertDialog / Toast
message, utilisez-legetActivity()
dans le paramètre context.A travaillé pour moi.
À votre santé!
la source
Essayez d'utiliser le contexte d'une activité qui sera sous la boîte de dialogue. Mais soyez prudent lorsque vous utilisez "ce" mot-clé, 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 "ceci", vous obtiendrez une exception, dans ce la boîte de dialogue de cas doit être connectée à l'activité hôte qui héberge tout et visible. (vous pouvez dire le contexte de l'activité parent la plus visible)
Je n'ai trouvé cette information dans aucun document mais en essayant. Ceci est ma solution sans fond solide, Si quelqu'un avec une meilleure connaissance, n'hésitez pas à commenter.
la source
Pour les futurs lecteurs, cela devrait aider:
la source
Dans mon cas, travaillez:
la source
Ou une autre possibilité est de créer une boîte de dialogue comme suit:
la source
Je pense que cela peut se produire également si vous essayez d'afficher une boîte de dialogue à partir d'un thread qui n'est pas le thread principal de l'interface utilisateur.
Utilisez
runOnUiThread()
dans ce cas.la source
Essayez
getParent()
à l'argument lieu de contexte comme newAlertDialog.Builder(getParent());
Hope ça marchera, ça a marché pour moi.la source
Après avoir jeté un œil à l'API, vous pouvez passer la boîte de dialogue de votre activité ou getActivity si vous êtes dans un fragment, puis le nettoyer avec force avec dialog.dismiss () dans les méthodes de retour pour éviter les fuites.
Bien que cela ne soit pas explicitement indiqué partout où je sais, il semble que vous ayez renvoyé la boîte de dialogue dans les OnClickHandlers juste pour le faire.
la source
Si votre boîte de dialogue crée sur l'adaptateur:
Passez l'activité au constructeur de l'adaptateur:
Recevez sur l'adaptateur:
Vous pouvez maintenant l'utiliser sur votre Builder
la source
Voici comment j'ai résolu la même erreur pour mon application:
Ajout de la ligne suivante après avoir créé la boîte de dialogue:
Vous n'aurez pas besoin d'acquérir un contexte. Cela est particulièrement utile si vous ouvrez une autre boîte de dialogue par-dessus la boîte de dialogue contextuelle actuelle. Ou quand il n'est pas pratique d'obtenir un contexte.
J'espère que cela peut vous aider avec le développement de votre application.
David
la source
la source