Narrensichere Art, mit Fragmenten bei Orientierungsänderungen umzugehen

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
}

Ich muss zwei Listenansichten nebeneinander anzeigen, das Menü links und den Inhalt rechts. Standardmäßig ist das erste Menü ausgewählt und sein Inhalt wird auf der rechten Seite angezeigt. Das Fragment, das den Inhalt anzeigt, lautet wie folgt:

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 und onCreateView werden zweimal aufgerufen . Es gibt viele Beispiele, die Fragmente verwenden. Da ich Anfänger in diesem Fach bin, kann ich das Beispiel nicht mit meinem Problem in Verbindung bringen. Ich brauche einen narrensicheren Weg, um mit Orientierungsänderungen umzugehen. Ich habe NICHT android:configChangesin Manifest-Datei deklariert . Ich muss die Aktivität zerstören und neu erstellen, damit ich im Querformat ein anderes Layout verwenden kann.

user1811741
quelle
Normalerweise werden Änderungen der Fragmentorientierung vorgenommen, ohne dass Sie etwas tun müssen. Was ist das Problem, wenn Sie die Ausrichtung ändern?
Alexander Kulyakhtin
Alex Ich benötige das Fragment DetailPart1 der Klasse, um das Layout mit listView im Hochformat und das Layout mit der Rasteransicht im Querformat anzuzeigen. Dazu muss ich das Fragment jedes Mal neu erstellen, aber ich möchte nicht dieselben Datensätze erneut laden, also i Speichern Sie sie in onSaveInstanceState. Aber der obige Code erstellt DetailPart1 zweimal neu. Ich muss den fehlenden Code kennen, damit er wie gewünscht
funktioniert

Antworten:

132

Sie erstellen jedes Mal ein neues Fragment, wenn Sie den Bildschirm in Ihrer Aktivität drehen. onCreate();Sie behalten jedoch auch die alten bei super.onCreate(savedInstanceState);. Setzen Sie also möglicherweise ein Tag und suchen Sie das Fragment, falls vorhanden, oder übergeben Sie das Null-Bundle an super.

Ich habe eine Weile gebraucht, um zu lernen, und es kann wirklich ein Bi **** sein, wenn Sie mit Sachen wie Viewpager arbeiten.

Ich würde Ihnen empfehlen, ein zusätzliches Mal über Fragmente zu lesen, da genau dieses Thema behandelt wird.

Hier ist ein Beispiel für den Umgang mit Fragmenten bei einer regelmäßigen Orientierungsänderung:

Aktivität :

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
quelle
Vielen Dank an Warpzit für Ihre Bemühungen, aber ich freue mich, wenn Sie im Code Ihren Standpunkt erläutern. So ändern Sie meinen Code, um Orientierungsänderungen zu verarbeiten, ohne das Fragment neu zu laden.
user1811741
1
Daher muss das Layout des Fragments bei der Ausrichtung geändert werden, aber ich möchte nicht alle Datensätze neu laden. Ich habe 1. android: configchanges = "Ausrichtung" im Manifest hinzugefügt. 2. onConfigurationChanged im Fragment überschreiben und die Ausrichtung erkennen und Listenansicht oder Rasteransicht je nach Ausrichtung ausblenden / anzeigen. Dies ist der richtige Weg?
user1811741
@ user1811741 mit Beispiel aktualisiert. Ich hoffe es klärt alles.
Warpzit
@Warpzit Wie kann das gleiche Szenario bei der Implementierung des ViewPager-Fragments behandelt werden, da ViewPager sich um alle angezeigten Fragmente kümmert?
CoDe
1
@Shubh Nun, ich glaube, Viewpager handhabt dies richtig. Wenn nicht, müssen Sie die getItem-Implementierung überschreiben, um Ihren Anforderungen zu entsprechen. Hoffe das hat dich in die richtige Richtung
gelenkt
21

Eine gute Richtlinie zum Speichern von Daten zwischen Orientierungsänderungen und der Wiederherstellung von Aktivitäten finden Sie in den Android-Richtlinien .

Zusammenfassung:

  1. Machen Sie Ihr Fragment haltbar:

    setRetainInstance(true);
  2. Erstellen Sie nur bei Bedarf ein neues Fragment (oder nehmen Sie zumindest Daten daraus)

    dataFragment = (DataFragment) fm.findFragmentByTag("data");
    
    // create the fragment and data the first time
    if (dataFragment == null) {
    
Sergej Werfel
quelle
schön Rette meine Zeit wah
Arjun saini