J'ai un fragment (F1) avec une méthode publique comme celle-ci
public void asd() {
if (getActivity() == null) {
Log.d("yes","it is null");
}
}
et oui quand je l'appelle (à partir de l'activité), c'est nul ...
FragmentTransaction transaction1 = getSupportFragmentManager().beginTransaction();
F1 f1 = new F1();
transaction1.replace(R.id.upperPart, f1);
transaction1.commit();
f1.asd();
Ce doit être quelque chose que je fais très mal, mais je ne sais pas ce que c'est
getActivity()
. De plus, comment instanciez-vous le fragment? L'avez-vous dans votre layout.xml?Réponses:
commit
planifie la transaction, c'est-à-dire qu'elle ne se produit pas tout de suite mais est planifiée comme un travail sur le thread principal la prochaine fois que le thread principal est prêt.Je suggère d'ajouter un
méthode à votre
Fragment
et en mettant un point d'arrêt dessus et en voyant quand il est appelé par rapport à votre appelasd()
. Vous verrez qu'il est appelé après la méthode où vous faites l'appel auxasd()
sorties. L'onAttach
appel est l'endroit où leFragment
est attaché à son activité et à partir de ce pointgetActivity()
retournera non nul (nb il y a aussi unonDetach()
appel).la source
onCreateView
ouonActivityCreated
. Je me demande pourquoi asd () doit être appelé quand il le fait dans la publication des questions.commitNow()
Le mieux pour s'en débarrasser est de conserver la référence d'activité lorsque onAttach est appelé et d'utiliser la référence d'activité là où c'est nécessaire, par exemple
la source
onDestroy()
etonDetach()
parce qu'ilonDestroy()
n'est pas garanti d'être appelé.Activity
si nous ne l'annulons pasonDestroy()
?Cela se produit lorsque vous appelez
getActivity()
un autre thread qui s'est terminé après la suppression du fragment. Le cas typique est l'appelgetActivity()
(par exemple pour aToast
) lorsqu'une requête HTTP est terminée (onResponse
par exemple).Pour éviter cela, vous pouvez définir un nom de champ
mActivity
et l'utiliser à la place degetActivity()
. Ce champ peut être initialisé dans la méthode onAttach () de Fragment comme suit:Dans mes projets, je définis généralement une classe de base pour tous mes fragments avec cette fonctionnalité:
Bon codage,
la source
Activity
partir d'un autre fil. Vous ne pouvez rien faire avec ça de toute façon, même pas montrer un toast. Vous devez donc soit transférer d'abord le travail vers le thread principal, soit ne pas utiliser d'activité du tout.Les autres réponses qui suggèrent de garder une référence à l'activité dans onAttach suggèrent simplement un pansement au problème réel. Lorsque getActivity renvoie null, cela signifie que le fragment n'est pas attaché à l'activité. Le plus souvent, cela se produit lorsque l'activité a disparu en raison de la rotation ou de la fin de l'activité, mais que le fragment a toujours une sorte d'écouteur de rappel enregistré. Lorsque l'auditeur est appelé, si vous devez faire quelque chose avec l'activité mais que l'activité a disparu, vous ne pouvez pas faire grand-chose. Dans votre code, vous devez simplement vérifier
getActivity() != null
et si ce n'est pas là, ne faites rien. Si vous conservez une référence à l'activité qui a disparu, vous empêchez l'activité d'être récupérée. Toutes les actions de l'interface utilisateur que vous pourriez essayer de faire ne seront pas vues par l'utilisateur. Je peux imaginer des situations où, dans l'écouteur de rappel, vous voudrez peut-être avoir un contexte pour quelque chose de non lié à l'interface utilisateur, dans ces cas, il est probablement plus logique d'obtenir le contexte de l'application. Notez que la seule raison pour laquelle l'onAttach
astuce n'est pas une grosse fuite de mémoire est que normalement après l'exécution de l'écouteur de rappel, il ne sera plus nécessaire et peut être récupéré avec le fragment, toutes ses vues et le contexte d'activité. Si voussetRetainInstance(true)
il y a un plus grand risque de fuite de mémoire car le champ Activité sera également conservé mais après la rotation, cela pourrait être l'activité précédente et non l'actuelle.la source
Depuis le niveau 23 d'API Android, onAttach (activité d'activité) est obsolète. Vous devez utiliser onAttach (contexte de contexte). http://developer.android.com/reference/android/app/Fragment.html#onAttach(android.app.Activity)
L'activité est un contexte, donc si vous pouvez simplement vérifier le contexte est une activité et la cast si nécessaire.
la source
PJL a raison. J'ai utilisé sa suggestion et voici ce que j'ai fait:
variables globales définies pour le fragment:
private final Object attachingActivityLock = new Object();
private boolean syncVariable = false;
mis en œuvre
3. J'ai terminé ma fonction, où j'ai besoin d'appeler getActivity (), dans thread, car si elle s'exécutait sur le thread principal, je bloquerais le thread avec l'étape 4. et onAttach () ne serait jamais appelé.
4. dans ma fonction où j'ai besoin d'appeler getActivity (), je l'utilise (avant l'appel getActivity ())
Si vous avez des mises à jour de l'interface utilisateur, n'oubliez pas de les exécuter sur le fil de l'interface utilisateur. J'ai besoin de mettre à jour ImgeView donc j'ai fait:
la source
L'ordre dans lequel les rappels sont appelés après commit ():
J'avais besoin de faire un travail qui impliquait des vues, donc onAttach () ne fonctionnait pas pour moi; il s'est écrasé. J'ai donc déplacé une partie de mon code qui définissait certains paramètres dans une méthode appelée juste après commit () (1.), puis l'autre partie du code qui gérait la vue à l'intérieur de onCreateView () (3.).
la source
J'utilise OkHttp et je viens de faire face à ce problème.
Pour la première partie, @thucnguyen était sur la bonne voie .
Certains appels HTTP étaient en cours d'exécution même après la fermeture de l'activité (car cela peut prendre un certain temps pour qu'une requête HTTP soit terminée). J'ai ensuite
HttpCallback
essayé de mettre à jour certains champs Fragment et j'ai obtenu unenull
exception en essayant de le fairegetActivity()
.IMO, la solution est d' empêcher les rappels de se produire lorsque le fragment n'est plus en vie (et ce n'est pas seulement avec Okhttp).
Le correctif: la prévention.
Si vous regardez le cycle de vie des fragments (plus d'informations ici ), vous remarquerez qu'il existe des méthodes
onAttach(Context context)
etonDetach()
. Ceux-ci sont appelés après que le fragment appartient à une activité et juste avant de cesser de l'être respectivement.Cela signifie que nous pouvons empêcher ce rappel de se produire en le contrôlant dans la
onDetach
méthode.la source
Où appelez-vous cette fonction? Si vous l'appelez dans le constructeur de
Fragment
, il retourneranull
.Appelez simplement
getActivity()
lorsque la méthodeonCreateView()
est exécutée.la source
Faites comme suit. Je pense que cela vous sera utile.
la source
Ceux qui ont encore le problème avec onAttach (activité d'activité), il vient de changer en contexte -
Dans la plupart des cas, la sauvegarde du contexte vous suffira - par exemple, si vous voulez faire getResources (), vous pouvez le faire directement à partir du contexte. Si vous devez encore intégrer le contexte à votre activité, faites-le -
Comme suggéré par user1868713.
la source
Vous pouvez utiliser onAttach ou si vous ne voulez pas mettre onAttach partout, vous pouvez mettre une méthode qui retourne ApplicationContext sur la classe App principale:
Après cela, vous pouvez le réutiliser partout dans tout votre projet, comme ceci:
S'il vous plaît laissez-moi savoir si cela ne fonctionne pas pour vous.
la source
Une autre bonne solution serait d'utiliser LiveData d'Android avec l'architecture MVVM. Vous définiriez un objet LiveData dans votre ViewModel et l'observeriez dans votre fragment, et lorsque la valeur LiveData est modifiée, il avertirait votre observateur (fragment dans ce cas) uniquement si votre fragment est à l'état actif, il serait donc garanti que vous ferait fonctionner votre interface utilisateur et accéder à l'activité uniquement lorsque votre fragment est à l'état actif. C'est l'un des avantages de LiveData
Bien sûr, lorsque cette question a été posée pour la première fois, il n'y avait pas de LiveData. Je laisse cette réponse ici parce que, comme je le vois, il y a toujours ce problème et cela pourrait être utile à quelqu'un.
la source
Appelez la méthode getActivity () dans onActivityCreated ()
la source