Android - Speichern / Wiederherstellen Fragment Zustand

? Stanete @ | Original: StackOverFlow
---

Ich habe eine Aktivität, in dem ich über mehrere Fragmente zu gehen. In jedem Fragment Ich habe mehrere Ansichten ( EditText, Listview, Karte, etc).

Wie kann ich speichern Sie die Instanz des Fragments, das in dem Moment dargestellt wird ? Ich brauche es, zu arbeiten, wenn die Aktivität onPause () -> onResume (). Auch ich brauche, um zu arbeiten, als ich von einem anderen Fragment (Pop aus Backstack ) zurückzukehren.

Vom Hauptaktivitätnenne ich das erste Fragment, dann aus der das Fragment nenne ich die nächste.

Code für meine Aktivität:

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

Dann ist hier der Code für eine meiner Fragmente :

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

            });
        }}

Ich habe eine Menge von Informationen, aber nichts klar durchsucht. Kann jemand eine klare Lösung und ein Beispiel zu geben, bitte?

---

Top 5 Antwort

1Raanan @

Um das Fragment Zustand Sie implementieren onSaveInstanceState() müssen sparen: " Auch wie eine Tätigkeit, können Sie den Zustand eines Fragments mit einem Bundle zu behalten, für den Fall, Prozess der Tätigkeit getötet wird, und Sie müssen, um das Fragment Zustand wiederherzustellen, wenn die Aktivität neu erstellt . Sie können den Zustand während des Fragments onSaveInstanceState save () Rückruf und wiederherstellen entweder während onCreate (), onCreateView () oder onActivityCreated (). Für weitere Informationen über Sparmodus finden Sie die Aktivitäten -Dokument. "

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

2cypressious @

Wenn ein Fragment an dem Backstack bewegt wird, wird es nicht zerstört wird. Alle Instanzvariablen bleiben dort . Das ist also der Ort, um Ihre Daten zu sichern. In onActivityCreated können Sie die folgenden Bedingungen zu prüfen :

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: Hier ist ein Beispiel

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 @

Sie können aktuelle Fragment von Fragment -Manager, und wenn nicht von ihnen in Fragment -Manager erhalten Sie Fragment_1 erstellen

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


    }


}

auch Sie können setReatinInstance auf true zu verwenden, was er tun wird es zu ignorieren onDestroy Verfahren in Fragment und Ihre Anwendung geht auf Masse zurück und os töten Ihre Anwendung mehr Speicher zuzuweisen, müssen Sie alle Daten, die Sie in onSaveInstanceState Bündel müssen sparen

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 @

Ich bin mir nicht ganz sicher, ob diese Frage immer noch stört Sie, weil es war mehrere Monate. Aber ich möchte zu teilen, wie ich damit beschäftigt. Hier ist der Quellcode :

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

Und hier ist der 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;
    }
}

Das ist der Schlüsselpunkt parentView . Normalerweise, wenn onCreateView, verwenden wir nur Rück RootView . Aber jetzt, ich RootView zu parentView hinzufügen und dann zurück parentView . Um zu verhindern, Fehler "Der angegebene Kind bereits ein Elternteil. Sie müssen RemoveView () auf dem ... nennen ", müssen wir " parentView.removeView ( RootView ) " nennen, oder der Methode, die ich geliefert, ist nutzlos. Außerdem möchte ich zu teilen, wie ich es gefunden. Zunächst stellte ich einen boolean, um anzuzeigen, wenn die Instanz besteht. Wenn die Instanz vorhanden ist, wird die RootView nicht wieder aufgepumpt werden. Aber dann gab Logcat das Kind bereits eine übergeordnete Sache, also beschloss ich, einen anderen Elternteil als Zwischen Eine Ebene zu verwenden. Das ist, wie es funktioniert. Hoffe, es ist hilfreich für Sie .

5Sar @

Try this :

@Override
protected void onPause() {

    super.onPause();

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

@Override
protected void onResume() {

    super.onResume();

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

}

Hoffe, das hilft .

Auch Sie können diese Aktivität zu Tag in menifest Datei schreiben:

  android:configChanges="orientation|screenSize"

Good luck !!!