Android - salva / restore stato frammento

? Stanete @ | Original: StackOverFlow
---

Ho un'attività in cui vado attraverso diversi frammenti . In ogni frammento Ho diverse viste ( EditText, ListView, Mappa, ecc) .

Come posso salvare l'istanza del frammento che viene mostrato in quel momento ? Ho bisogno di lavorare quando l'attività è onPause ( ) - > onResume ( ) . Inoltre ho bisogno di lavorare quando torno da un altro frammento ( pop da backstack ) .

Dall'attività principale Chiamo il primo frammento, poi dal frammento che io chiamo il prossimo .

Codice per la mia attività:

public class Activity_Main extends FragmentActivity{

public static Fragment_1 fragment_1;
public static Fragment_2 fragment_2;
public static Fragment_3 fragment_3;
public static FragmentManager fragmentManager;

@Override
 protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

     fragment_1 = new Fragment_1();

     fragment_2 = new Fragment_2();

     fragment_3 = new Fragment_3();

     fragmentManager = getSupportFragmentManager();
     FragmentTransaction transaction_1 = fragmentManager.beginTransaction();
     transaction_1.replace(R.id.content_frame, fragment_1);
     transaction_1.commit();
}}

Poi ecco il codice per uno dei miei frammenti :

public class Fragment_1 extends Fragment {

      private EditText title;
      private Button go_next;


      @Override
      public View onCreateView(final LayoutInflater inflater,
        ViewGroup container, Bundle savedInstanceState) {

            View rootView = inflater.inflate(R.layout.fragment_1,
            container, false);

            title = (EditText) rootView.findViewById(R.id.title);

            go_next = (Button) rootView.findViewById(R.id.go_next);

            image.setOnClickListener(new View.OnClickListener() {

         @Override
         public void onClick(View v) {

                 FragmentTransaction transaction_2 = Activity_Main.fragmentManager
                .beginTransaction();

                 transaction_2.replace(R.id.content_frame,
                  Activity_Main.fragment_2);
                 transaction_2.addToBackStack(null);
                 transaction_2.commit();  

            });
        }}

Ho cercato un sacco di informazioni, ma nulla di chiaro . Qualcuno può dare una soluzione chiara e un esempio, per favore?

---

Top 5 Risposta

1Raanan @

Per salvare lo stato frammento è necessario implementare onSaveInstanceState() : " Anche come un'attività, è possibile mantenere lo stato di un frammento con un Bundle, in caso di processo del l'attività viene ucciso ed è necessario ripristinare lo stato frammento quando l'attività viene ricreata . È possibile salvare lo stato durante onSaveInstanceState del frammento ( ) callback e il ripristino durante o onCreate ( ), onCreateView ( ), o onActivityCreated ( ) . Per ulteriori informazioni sul salvataggio di stato, vedere il documento attività . "

http://developer.android.com/guide/components/fragments.html#Lifecycle

2cypressious @

Quando un frammento viene spostato nella backstack, non viene distrutta . Tutte le variabili di istanza rimangono lì . Quindi questo è il posto giusto per salvare i dati . In onActivityCreated di verificare le seguenti condizioni :

Is the bundle != null? If yes, that's where the data is saved (probably orientation change). Is there data saved in instance variables? If yes, restore your state from them (or maybe do nothing, because everything is as it should be). Otherwise your fragment is shown for the first time, create everything anew.

Edit : Ecco un esempio

public class ExampleFragment extends Fragment {
    private List<String> myData;

    @Override
    public void onSaveInstanceState(final Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putSerializable("list", (Serializable) myData);
    }

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

        if (savedInstanceState != null) {
            //probably orientation change
            myData = (List<String>) savedInstanceState.getSerializable("list");
        } else {
            if (myData != null) {
                //returning from backstack, data is fine, do nothing
            } else {
                //newly created, compute data
                myData = computeData();
            }
        }
    }
}
3Constantin Cerberus @

È possibile ottenere Frammento corrente direttore frammento e, se non di loro in gestione frammento è possibile creare Fragment_1

public class MainActivity extends FragmentActivity {


    public static Fragment_1 fragment_1;
    public static Fragment_2 fragment_2;
    public static Fragment_3 fragment_3;
    public static FragmentManager fragmentManager;


    @Override
    protected void onCreate(Bundle arg0) {
        super.onCreate(arg0);
        setContentView(R.layout.main);

        fragment_1 = (Fragment_1) fragmentManager.findFragmentByTag("fragment1");

        fragment_2  =(Fragment_2) fragmentManager.findFragmentByTag("fragment2");

        fragment_3 = (Fragment_3) fragmentManager.findFragmentByTag("fragment3");


        if(fragment_1==null && fragment_2==null && fragment_3==null){           
            fragment_1 = new Fragment_1();          
            fragmentManager.beginTransaction().replace(R.id.content_frame, fragment_1, "fragment1").commit();
        }


    }


}

inoltre è possibile utilizzare setReatinInstance per vero ciò che lo farà ignorare OnDestroy metodo frammento e l'applicazione andando a ritornare a terra e os uccidere l'applicazione per allocare più memoria è necessario per salvare tutti i dati è necessario in bundle onSaveInstanceState

public class Fragment_1 extends Fragment {


    private EditText title;
    private Button go_next;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true); //Will ignore onDestroy Method (Nested Fragments no need this if parent have it)
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        onRestoreInstanceStae(savedInstanceState);
        return super.onCreateView(inflater, container, savedInstanceState);
    }


    //Here you can restore saved data in onSaveInstanceState Bundle
    private void onRestoreInstanceStae(Bundle savedInstanceState){
        if(savedInstanceState!=null){
            String SomeText = savedInstanceState.getString("title");            
        }
    }

    //Here you Save your data
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("title", "Some Text");
    }

}
4butch @

Io non sono molto sicuro se questa domanda è ancora ti dà fastidio, dal momento che è stato diversi mesi . Ma vorrei condividere come ho affrontato questo . Ecco il codice sorgente :

int FLAG = 0;
private View rootView;
private LinearLayout parentView;

/**
 * The fragment argument representing the section number for this fragment.
 */
private static final String ARG_SECTION_NUMBER = "section_number";

/**
 * Returns a new instance of this fragment for the given section number.
 */
public static Fragment2 newInstance(Bundle bundle) {
    Fragment2 fragment = new Fragment2();
    Bundle args = bundle;
    fragment.setArguments(args);
    return fragment;
}

public Fragment2() {

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    super.onCreateView(inflater, container, savedInstanceState);
    Log.e("onCreateView","onCreateView");
    if(FLAG!=12321){
        rootView = inflater.inflate(R.layout.fragment_create_new_album, container, false);
        changeFLAG(12321);
    }       
    parentView=new LinearLayout(getActivity());
    parentView.addView(rootView);

    return parentView;
}

/* (non-Javadoc)
 * @see android.support.v4.app.Fragment#onDestroy()
 */
@Override
public void onDestroy() {
    // TODO Auto-generated method stub
    super.onDestroy();
    Log.e("onDestroy","onDestroy");
}

/* (non-Javadoc)
 * @see android.support.v4.app.Fragment#onStart()
 */
@Override
public void onStart() {
    // TODO Auto-generated method stub
    super.onStart();
    Log.e("onstart","onstart");
}

/* (non-Javadoc)
 * @see android.support.v4.app.Fragment#onStop()
 */
@Override
public void onStop() {
    // TODO Auto-generated method stub
    super.onStop();
    if(false){
        Bundle savedInstance=getArguments();
        LinearLayout viewParent;

        viewParent= (LinearLayout) rootView.getParent();
        viewParent.removeView(rootView);

    }
    parentView.removeView(rootView);

    Log.e("onStop","onstop");
}
@Override
public void onPause() {
    super.onPause();
    Log.e("onpause","onpause");
}

@Override
public void onResume() {
    super.onResume();
    Log.e("onResume","onResume");
}

E qui è il MainActivity :

/**
 * Fragment managing the behaviors, interactions and presentation of the
 * navigation drawer.
 */
private NavigationDrawerFragment mNavigationDrawerFragment;

/**
 * Used to store the last screen title. For use in
 * {@link #restoreActionBar()}.
 */

public static boolean fragment2InstanceExists=false;
public static Fragment2 fragment2=null;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    setContentView(R.layout.activity_main);

    mNavigationDrawerFragment = (NavigationDrawerFragment) getSupportFragmentManager()
            .findFragmentById(R.id.navigation_drawer);
    mTitle = getTitle();

    // Set up the drawer.
    mNavigationDrawerFragment.setUp(R.id.navigation_drawer,
            (DrawerLayout) findViewById(R.id.drawer_layout));
}

@Override
public void onNavigationDrawerItemSelected(int position) {
    // update the main content by replacing fragments
    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction=fragmentManager.beginTransaction();
    switch(position){
    case 0:
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.replace(R.id.container, Fragment1.newInstance(position+1)).commit();
        break;
    case 1:

        Bundle bundle=new Bundle();
        bundle.putInt("source_of_create",CommonMethods.CREATE_FROM_ACTIVITY);

        if(!fragment2InstanceExists){
            fragment2=Fragment2.newInstance(bundle);
            fragment2InstanceExists=true;
        }
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.replace(R.id.container, fragment2).commit();

        break;
    case 2:
        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.replace(R.id.container, FolderExplorerFragment.newInstance(position+1)).commit();
        break;
    default: 
        break;
    }
}

Il parentView è il punto chiave . Normalmente, quando onCreateView, usiamo appena il ritorno rootView . Ma ora, aggiungo rootView a parentView, e poi tornare parentView . Per evitare che "Il bambino specificato ha già un genitore . È necessario chiamare removeView ( ) sulla ... " errore, dobbiamo chiamare " parentView.removeView ( rootView ) ", o il metodo che ho fornito è inutile . Vorrei anche parlare di come l'ho trovato . In primo luogo, ho creato un valore booleano per indicare se l'istanza esiste . Quando esiste l'istanza, il rootView non verrà gonfiato nuovo . Ma poi, logcat ha dato il bambino ha già una cosa genitore, così ho deciso di utilizzare un altro genitore come un genitore intermedio View . Ecco come funziona . Spero che sia utile a voi .

5Sar @

Try this :

@Override
protected void onPause() {

    super.onPause();

    getSupportFragmentManager().findFragmentByTag("MyFragment")
            .setRetainInstance(true);
}

@Override
protected void onResume() {

    super.onResume();

    getSupportFragmentManager().findFragmentByTag("MyFragment")
            .getRetainInstance();

}

Spero che questo vi aiuterà .

Inoltre è possibile scrivere questo per tag attività in menifest di file :

  android:configChanges="orientation|screenSize"

Good luck !!!