139 votes

fragment d’Android - comment sauver les États de vues dans un fragment lorsqu’un autre fragment est poussé dessus

Dans android, un fragment (disons FragA) est ajouté à la backstack et un autre fragment (disons FragB) vient vers le haut. Maintenant, sur la frappe de retour FragA vient vers le haut et l' onCreateView() est appelé. Maintenant, j'ai eu FragA dans un état particulier avant d' FragB a été repoussée sur le dessus de cela.

Ma Question est comment puis-je restaurer FragA à son état précédent ? Est-il un moyen d'enregistrer l'état (comme, disons, dans un ensemble) et si oui, alors quelle méthode dois-je remplacer ?

97voto

ania Points 1583

Vous trouverez dans le guide de fragment FragmentList exemple :

Que vous pouvez utiliser plus tard comme ceci :

Je suis un débutant en Fragments, mais il semble que la solution de votre problème  ;) OnActivityCreated est appelé une fois le fragment renvoie de la pile de retour.

87voto

Fyodor Volchyok Points 31

Fragment de l' onSaveInstanceState(Bundle outState) ne sera jamais appelée à moins que fragment de l'activité de l'appeler sur lui-même et attaché fragments. Ainsi, cette méthode ne sera pas appelé jusqu'à ce que quelque chose (généralement de rotation) de la force de l'activité SaveInstanceState et le restaurer plus tard. Mais si vous avez une seule activité et grand ensemble de fragments à l'intérieur (avec une utilisation intensive de l' replace) et l'application ne fonctionne que dans une seule orientation de l'activité de l' onSaveInstanceState(Bundle outState) ne peut pas être appelé pour un long moment.

Je sais que trois solutions possibles.

La première:

l'utilisation du fragment arguments pour contenir les données importantes:

public class FragmentA extends Fragment {
    private static final String PERSISTENT_VARIABLE_BUNDLE_KEY = "persistentVariable";

    private EditText persistentVariableEdit;

    public FragmentA() {
        setArguments(new Bundle());
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_a, null);

        persistentVariableEdit = (EditText) view.findViewById(R.id.editText);

        TextView proofTextView = (TextView) view.findViewById(R.id.textView);

        Bundle mySavedInstanceState = getArguments();
        String persistentVariable = mySavedInstanceState.getString(PERSISTENT_VARIABLE_BUNDLE_KEY);

        proofTextView.setText(persistentVariable);


        view.findViewById(R.id.btnPushFragmentB).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getFragmentManager()
                        .beginTransaction()
                        .replace(R.id.frameLayout, new FragmentB())
                        .addToBackStack(null)
                        .commit();
            }
        });

        return view;
    }

    @Override
    public void onPause() {
        super.onPause();
        String persistentVariable = persistentVariableEdit.getText().toString();

        getArguments().putString(PERSISTENT_VARIABLE_BUNDLE_KEY, persistentVariable);
    }
}

- La seconde, mais moins pédantesque - maintenez les variables dans les singletons

Le troisième ne l'a pas) replace() des fragments, mais add()/show()/hide() .

20voto

e_v_e Points 51

Il suffit de remarquer que si vous travaillez avec des Fragments à l'aide de ViewPager, il est assez facile. Vous avez seulement besoin d'appeler cette méthode: setOffscreenPageLimit().

Accordign pour les docs:

Définir le nombre de pages qui doivent être conservés pour chaque côté de la page en cours dans le point de vue de la hiérarchie dans un état d'inactivité. Pages au-delà de cette limite sera recréé à partir de l'adaptateur en cas de besoin.

Simmilar question ici

9voto

rmirabelle Points 822

J'ai travaillé avec un problème très similaire à cela. Car je savais que je serait souvent le retour à un fragment précédent, j'ai vérifié pour voir si le fragment .isAdded() était vrai, et si oui, plutôt que de faire un transaction.replace() je viens de faire un transaction.show(). Cela permet de maintenir le fragment de la recréation si elle est déjà sur la pile - pas d'état d'économie d'nécessaire.

Fragment target = <my fragment>;
FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
if(target.isAdded()) {
    transaction.show(target);
} else {
    transaction.addToBackStack(button_id + "stack_item");
    transaction.replace(R.id.page_fragment, target);
}
transaction.commit();

Une autre chose à garder à l'esprit est que, bien que cela préserve l'ordre naturel des fragments eux-mêmes, vous pourriez encore besoin de gérer l'activité elle-même être détruits et recréés sur l'orientation (config). Pour contourner ce problème dans AndroidManifest.xml pour votre noeud:

android:configChanges="orientation|screenSize"

Dans Android 3.0 et supérieur, l' screenSize est apparemment nécessaire.

Bonne chance

5voto

Brook Oldre Points 41

Si vous gérez les modifications de configuration dans votre activité de fragment spécifiée dans le manifeste d’android comme ceci

puis l’onSaveInstanceState du fragment ne puisse être appelé et l’objet savedInstanceState sera toujours null.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X