web-dev-qa-db-fra.com

OnCreateView appelé plusieurs fois / Utilisation d'ActionBar et de fragments

J'ai changé une partie de mon application d'activités en fragments pour pouvoir utiliser les onglets ActionBar soignés.

Cependant, après avoir terminé la transition, j'ai rencontré un problème: chaque fois que je passe à un autre onglet, ce fragment est recréé à nouveau. OnCreate et onCreateView sont appelés à chaque fois que j'arrive à un onglet.

J'ai 4 onglets, dont chacun est destiné à ouvrir l'un de ces fragments:

Fragment ShopFragment = new WebActivity();
Fragment SearchFragment = new SearchActivity(context);
Fragment StoreFragment = new StoreLocatorActivity(context, this);
Fragment BlogsFragment = new BlogsActivity(context, this);

Voici mon code pour l'auditeur:

    class MyTabsListener implements ActionBar.TabListener {
        public Fragment fragment;

        public MyTabsListener(Fragment fragment) {
            this.fragment = fragment;
        }

        @Override
        public void onTabReselected(Tab tab, FragmentTransaction ft) {
            ft.hide(fragment);
        }

        @Override
        public void onTabSelected(Tab tab, FragmentTransaction ft) {
            ft.replace(R.id.fragment_container, fragment);
        }

        @Override
        public void onTabUnselected(Tab tab, FragmentTransaction ft) {          

        }

    }

Quelqu'un pourrait-il m'orienter dans la bonne direction?

40
Sorin Cioban

Lorsque vous appelez FragmentTransaction.replace (...) , Android exécutera efficacement une séquence de FragmentTransaction.remove (...) (pour tous les fragments actuellement ajoutés à ce conteneur) et FragmentTransaction.add (...) (pour votre fragment fourni). La suppression d'un fragment du FragmentManager entraînera la fragmentation du fragment. détruit et son état ne sera plus géré. Plus particulièrement, lorsque vous ajouterez à nouveau le fragment, toutes les vues seront réinitialisées. Remarque: étant donné que vous réutilisez la même instance de fragment, le fragment conservera toujours la valeur de toutes les variables d'instance. .

Une solution à ce problème serait d'utiliser FragmentTransaction.detach (Fragment) et FragmentTransaction.attach (Fragment) lors de la commutation. Cela entraînera la recréation des vues Fragment (onDestroyView() & onCreateView() sera appelée), mais le paquet d'état d'instance sera enregistré et vous sera rendu entre les appels et donc l'état d'affichage peut être maintenu. C'est l'approche adoptée par FragmentPagerAdapter lorsqu'il essaie de basculer entre les fragments.

Alternativement, vous pouvez autoriser la destruction des fragments, mais conserver leur état de sauvegarde indépendamment pour eux. Cela utiliserait moins de mémoire, au détriment d'un temps de commutation plus lent. Les méthodes à noter seraient FragmentManager.saveFragmentInstanceState (Fragment) et FragmentManager.setInitialSavedState (Fragment.SavedState) , en conjonction avec l'ajout/la suppression. C'est l'approche adoptée par FragmentStatePagerAdapter .

Vous pouvez jeter un oeil au source pour FragmentPagerAdapter et au source pour FragmentStatePagerAdapter pour les conseils d'implémentation.

47
antonyt

Il y a l'option show / hide juste pour que les fragments n'aient pas besoin d'être repeints/recréés et les onCreate() et onCreateView() ne sera pas invoqué à nouveau.

7
AlikElzin-kilaka