Gestion du cycle de vie Android des fragments dans ViewPager et FragmentPagerAdapter
J'ai eu du mal à trouver la bonne gestion de Fragments à l'intérieur d'un FragmentActivity
avec un ViewPager
est. Avant d'entrer dans les détails, un bref résumé de la question que je suis confronté est le suivant:
J'ai un FragmentActivity
avec un ViewPager
. Le ViewPager
utilise une coutume, pourtant très simple FragmentPagerAdapter
. Chaque Fragment
dans le ViewPager
compose d'une ExpandableListView
. J'ai aussi une barre d'action le bouton "Actualiser". Pour l'instant, supposons que le ViewPager
n'a qu'un seul Fragment
. L'activité est créée, et le Fragment
's ExpandableListView
est rempli (so far so good). Lorsque l'Actualisation bouton est cliqué, la méthode de gestion au sein de la FragmentActivity
parcourt la liste des Fragments
qui sont affectés à la FragmentPagerAdapter et les appels refresh()
sur chaque Fragment
pour remplir sa Liste. Toutefois, lorsque l'orientation de l'appareil changements (par exemple de portrait à paysage), l'Activité est recréée et sont donc les fragments. En cliquant sur le bouton Actualiser maintenant va itérer sur les non-initialisées Fragments
.
Je sais que je suis très vague, et surtout sans exemple de code, mais s'il vous plaît garder avec moi. J'ai fait remonter le problème et les appels de méthode comme suit à partir du début de la demande/de l'activité:
FragmentActivity.onCreate()
FragmentActivity.setContentView()
FragmentActivity.createPagerFragments()
<-- cela crée une liste de tableaux de Fragments et assignes à un nouveau FragmentPagerAdapter qui est à son tour affecté à la ViewPager.Fragment.onAttach()
Fragment.onCreate()
< - rien de spécial ici, il suffit d'appeler la méthode super.Fragment.onCreateView()
< - rien de spécial, juste de gonfler la mise en pageFragment.onActivityCreated()
<-- rien ici non plus.- << Toutes les bonnes, les changements d'orientation de l'ici >>
FragmentActivity.onCreate()
Fragment.onAttach()
Fragment.onCreate()
FragmentActivity.setContentView()
FragmentActivity.createPagerFragments()
Fragment.onCreateView()
Fragment.onActivityCreated()
- << Actualiser le bouton cliqué >>
FragmentActivity.refresh()
<-- effectue une itération nouvellement créé Fragments de #13 (pas ces par Android!).- << Crash: NullPointerException pour mExpandableListView dans le Fragment. >>
Donc, le problème, comme je le vois, est comme suit:
Quand Android re-crée le FragmentActivity
et ses Views
après un changement d'orientation de l'écran (appels #9 à 15 ci-dessus), il crée de nouvelles Fragment
objets avec leur état restauré à ce que les originaux ont été. Cependant, celles-ci semblent être complètement géré par le FragmentManager
, et non pas par le FragmentPagerAdapter
. En revanche, lorsque la FragmentPagerAdapter
est re-créé avec le Fragments
dans l'activité de onCreate
méthode (voir appel n ° 13) la Fragments
affectés à l'adaptateur n'ont jamais de leur Fragment.onCreate()
ou Fragment.onCreateView()
méthodes appelées à tous. Ainsi, lorsque la méthode refresh() est appelée (voir n ° 17), la méthode effectue une itération sur ces Fragments
qui n'ont pas été initialisés. Par conséquent, lorsqu'ils essaient de remplir le ExpandableListView
, le point de vue de la variable d'instance est NULL
. Ceci est dû au fait que la variable d'instance est affecté uniquement dans le Fragment.onCreateView()
méthode, qui n'est jamais appelée sur ces Fragments
.
Donc ma question est: comment bien faire ré-utilisation de la re-recréé (Android) Fragments
après l'orientation de l'écran a changé afin d'éviter d'en créer de nouvelles qui ne sont pas initialisées? J'ai besoin d'avoir une référence valide, afin d'appeler la méthode refresh() qui renseigne sur la demande. Idéalement, ils devraient également être attribuée à la FragmentPagerAdapter
.
J'espère avoir été clair dans la description du problème, et la raison pour laquelle je n'ai pas fourni un exemple de code est parce que le problème peut être vu) n'est pas dans le code lui-même, mais à partir d'un plutôt incorrect (seemigly) re-création de Fragments plutôt que de ré-utilisation. Mais si nécessaire, je peux vous donner un exemple de code, je viens, par ce moyen serait plus clair.
Merci!
source d'informationauteur vmivanov
Vous devez vous connecter pour publier un commentaire.
C'est beaucoup de choses à lire, mais après avoir lu l'introduction et la question et avoir de l'expérience avec FragmentStatePagerAdapter, qui est similaire à FragmentPagerAdapter je peux vous dire que:
Après la rotation de votre carte sera AUTOMATIQUEMENT joindre vieux fragments. Il semble donc que, bien que l'activité de création de carte est recréé, FragmentManager, qui est global et il est instance de préserver l'activité de loisirs va détecter que les nouveaux FragmentStatePagerAdapter est combinée avec le même ViewPager et de la demande pour les mêmes Fragments et tout simplement de les récupérer à partir du Fragment BackStack.
Vous en tant que concepteur de Fragments pouvez remarquer ce problème en continue invocation de Fragment.onAttach() et le Fragment.onDetach(). Lorsque onAttach() se produit, c'est soit de la création de votre Fragment ou de le réutiliser après la rotation. Vous devriez être capable de distinguer ce Fragment a été tourné avec l'utilisation de rappel onRestoreRnstanceState().
Vous le verrez dans les journaux, de nombreux onCreate() et d'autres états journaux simultanément, parce que FragmentStatePagerAdapter toujours extrait/crée min 3 Fragments (sauf si vous définissez qu'ils ne sont que 2 ou 1), de même, après la rotation de l'écran 3 fragments seront remis en place à partir de backstack.
J'espère que cela a aidé.
Je crois que ce questionà propos de la récupération de l'actuel fragment d'un ViewPager, vous aidera. Comme l'a déjà souligné, les fragments sont gérés par le Fragment(État)PagerAdapter et PAS d'Activité ou d'un Fragment de son cycle de vie.
getItem
méthode. Cette méthode est appelée une seule fois par fragment, même si l'activité soit recréé.instantiateItem
méthode. Plus probablement, c'est le lieu, où vous avez besoin pour obtenir vos fragments et d'appeler leur actualisation des méthodes.Comment à propos de l'ajout de l'Activité de la Balise dans votre manifeste:
ou cette API de 13 ou plus
afin de ne pas recréer vos fragments en cas de changement d'orientation..