Manière infaillible de gérer le fragment lors du changement d'orientation

87
public class MainActivity extends Activity implements MainMenuFragment.OnMainMenuItemSelectedListener {

 @Override
 public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    FragmentManager fragmentManager = getFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager
            .beginTransaction();

    // add menu fragment
    MainMenuFragment myFragment = new MainMenuFragment();
    fragmentTransaction.add(R.id.menu_fragment, myFragment);

    //add content
    DetailPart1 content1= new DetailPart1 ();
    fragmentTransaction.add(R.id.content_fragment, content1);
    fragmentTransaction.commit();

}
public void onMainMenuSelected(String tag) {
  //next menu is selected replace existing fragment
}

J'ai besoin d'afficher deux vues de liste côte à côte, le menu à gauche et son contenu à droite. Par défaut, le premier menu est sélectionné et son contenu est affiché sur le côté droit. Le fragment qui affiche le contenu est comme ci-dessous:

public class DetailPart1 extends Fragment {
  ArrayList<HashMap<String, String>> myList = new ArrayList<HashMap<String, String>>();
  ListAdapter adap;
  ListView listview;

  @Override
  public void onActivityCreated(Bundle savedInstanceState) {
      super.onActivityCreated(savedInstanceState);

       if(savedInstanceState!=null){
        myList = (ArrayList)savedInstanceState.getSerializable("MYLIST_obj");
        adap = new LoadImageFromArrayListAdapter(getActivity(),myList );
        listview.setAdapter(adap);
       }else{
        //get list and load in list view
        getlistTask = new GetALLListTasks().execute();
    }


     @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.skyview_fragment, container,false);
           return v;
        }


     @Override
      public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
          outState.putSerializable("MYLIST_obj", myList );
        }
    }

OnActivityCreated et onCreateView sont appelés deux fois . Il existe de nombreux exemples utilisant des fragments. Comme je suis débutant dans ce sujet, je suis incapable de relier l'exemple à mon problème. J'ai besoin d'un moyen infaillible pour gérer le changement d'orientation. Je n'ai PAS déclaré android:configChangesdans le fichier manifeste. J'ai besoin de l'activité détruire et recréer pour pouvoir utiliser une mise en page différente en mode paysage.

user1811741
la source
Les changements d'orientation des fragments sont généralement pris en charge sans que vous ayez à faire quoi que ce soit. Alors, quel est le problème que vous rencontrez lorsque vous changez d'orientation?
Alexander Kulyakhtin
Alex J'ai besoin du fragment de classe DetailPart1 pour afficher la mise en page avec listView en mode portrait et la mise en page avec Grid View en mode paysage.Pour cela, je dois recréer le fragment à chaque fois mais je ne veux pas charger à nouveau les mêmes enregistrements, donc je stockez-les à onSaveInstanceState .Mais le code ci-dessus recrée DetailPart1 deux fois, j'ai besoin de connaître le code manquant qui le fait fonctionner comme vous le souhaitez
user1811741

Réponses:

132

Vous créez un nouveau fragment à chaque fois que vous tournez l'écran dans votre activité onCreate();Mais vous maintenez également les anciens avec super.onCreate(savedInstanceState);. Alors peut-être définir la balise et trouver le fragment s'il existe, ou passer le bundle nul à super.

Cela m'a pris du temps à apprendre et cela peut vraiment être un bi **** lorsque vous travaillez avec des trucs comme viewpager.

Je vous recommande de lire un peu plus sur les fragments, car ce sujet exact est couvert.

Voici un exemple de gestion des fragments lors d'un changement d'orientation régulier:

Activité :

public class MainActivity extends FragmentActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (savedInstanceState == null) {
            TestFragment test = new TestFragment();
            test.setArguments(getIntent().getExtras());
            getSupportFragmentManager().beginTransaction().replace(android.R.id.content, test, "your_fragment_tag").commit();
        } else {
            TestFragment test = (TestFragment) getSupportFragmentManager().findFragmentByTag("your_fragment_tag");
        }
    }
}

Fragment :

public class TestFragment extends Fragment {

    public static final String KEY_ITEM = "unique_key";
    public static final String KEY_INDEX = "index_key";
    private String mTime;

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

        if (savedInstanceState != null) {
            // Restore last state
            mTime = savedInstanceState.getString("time_key");
        } else {
            mTime = "" + Calendar.getInstance().getTimeInMillis();
        }

        TextView title = (TextView) view.findViewById(R.id.fragment_test);
        title.setText(mTime);

        return view;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("time_key", mTime);
    }
}
Warpzit
la source
merci Warpzit pour votre effort, mais je serai heureux si vous expliquez dans le code à propos de votre point. Comment modifier mon code pour gérer le changement d'orientation sans recharger le fragment.
user1811741
1
Par conséquent, j'ai besoin que la disposition du fragment soit modifiée lors de l'orientation, mais je ne veux pas recharger tous les enregistrements, ce que j'ai fait était 1. ajouter android: configchanges = "orientation" dans le manifeste 2. remplacer onConfigurationChanged dans le fragment et détecter l'orientation et masquer / afficher la liste ou la grille en fonction de l'orientation .C'est la bonne façon?
user1811741
@ user1811741 mis à jour avec l'exemple. J'espère que cela clarifie tout.
Warpzit
@Warpzit Comment peut gérer le même scénario en cas d'implémentation du fragment ViewPager puisque ViewPager prend en charge tous les fragments affichés .. toute suggestion.
CoDe
1
@Shubh eh bien, je pense que viewpager gère cela correctement, sinon vous devrez remplacer l'implémentation getItem pour répondre à vos besoins. J'espère que cela vous a
orienté
21

Un bon guide sur la façon de conserver les données entre les changements d'orientation et les activités récréatives se trouve dans les directives Android .

Résumé:

  1. rendre votre fragment conservable:

    setRetainInstance(true);
  2. Créer un nouveau fragment uniquement si nécessaire (ou au moins en extraire des données)

    dataFragment = (DataFragment) fm.findFragmentByTag("data");
    
    // create the fragment and data the first time
    if (dataFragment == null) {
Sergej Werfel
la source
nice Save my time wah
Arjun saini