Un modo infallibile per gestire il frammento al cambio di orientamento


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
}

Ho bisogno di visualizzare due visualizzazioni elenco affiancate, il menu a sinistra e il suo contenuto a destra. Per impostazione predefinita, il primo menu è selezionato e il suo contenuto viene visualizzato sul lato destro. Il frammento che mostra il contenuto è il seguente:

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 e onCreateView vengono chiamati due volte . Ci sono molti esempi là fuori che utilizzano frammenti. Poiché sono un principiante in questo argomento, non sono in grado di collegare l'esempio con il mio problema. Ho bisogno di un modo infallibile per gestire il cambio di orientamento. NON ho dichiarato android:configChangesnel file manifest. Ho bisogno che l'attività venga distrutta e ricreata in modo da poter utilizzare layout diversi in modalità orizzontale.


Di solito i cambiamenti di orientamento dei frammenti vengono gestiti senza che tu debba fare nulla. Allora, qual è il problema che riscontri quando cambi l'orientamento?
Alexander Kulyakhtin

Alex Ho bisogno del frammento di classe DetailPart1 per visualizzare il layout con listView in modalità verticale e layout con Grid View in modalità orizzontale. Per questo, devo ricreare il frammento ogni volta ma non voglio caricare di nuovo gli stessi record, quindi ho memorizzali su onSaveInstanceState .Ma il codice sopra ricrea DetailPart1 due volte, ho bisogno di conoscere il codice mancante che lo fa funzionare come desiderato
user1811741

possibile duplicato del ciclo di vita
naXa

Risposte:


132

Stai creando un nuovo frammento ogni volta che giri lo schermo nella tua attività, onCreate();ma stai anche mantenendo quelli vecchi con super.onCreate(savedInstanceState);. Quindi forse imposta il tag e trova il frammento se esiste, o passa il bundle null a super.

Mi ci è voluto un po 'per imparare e può davvero essere un bi **** quando lavori con cose come viewpager.

Ti consiglio di leggere i frammenti un'altra volta poiché questo argomento esatto è trattato.

Ecco un esempio di come gestire i frammenti con un cambio di orientamento regolare:

Attività :

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");
        }
    }
}

Frammento :

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);
    }
}

grazie Warpzit per il tuo impegno, ma sarò felice se spiegherai in codice il tuo punto. Come modificare il mio codice per gestire il cambio di orientamento senza ricaricare il frammento.
user1811741

1
Quindi ho bisogno di cambiare il layout del frammento sull'orientamento, ma non voglio ricaricare tutti i record, quello che ho fatto è stato 1. aggiungere android: configchanges = "orientamento" nel manifest 2. sovrascrivere onConfigurationChanged nel frammento e rilevare l'orientamento e nascondi / mostra listview o gridview a seconda dell'orientamento. Questo è il modo giusto?
user1811741

@ user1811741 aggiornato con esempio. Spero che chiarisca tutto.
Warpzit

@Warpzit Come è possibile gestire lo stesso scenario in caso di implementazione di ViewPager Fragment poiché ViewPager si prende cura di tutti i frammenti visualizzati .. qualsiasi suggerimento.
CoDe

1
@Shubh, beh, credo che viewpager lo gestisca correttamente, altrimenti dovrai sovrascrivere l'implementazione getItem per soddisfare le tue esigenze. Spero che questo ti abbia indirizzato nella giusta direzione, se non hai posto una domanda corretta :)
Warpzit

21

Una buona linea guida su come conservare i dati tra i cambiamenti di orientamento e la ricreazione dell'attività può essere trovata nelle linee guida di Android .

Sommario:

  1. rendi il tuo frammento conservabile:

    setRetainInstance(true);
    
  2. Crea un nuovo frammento solo se necessario (o almeno prendi i dati da esso)

    dataFragment = (DataFragment) fm.findFragmentByTag("data");
    
    // create the fragment and data the first time
    if (dataFragment == null) {
    

bello Save my time wah
Arjun saini
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.