The best way to save and restore the Fragment state in Android is androidfragment.

Source: Internet
Author: User

The best way to save and restore the Fragment state in Android is androidfragment.

Probably be the best way (?) To save/restore Android Fragment's state so far

Key Point: Arguments of Fragment.

After using Fragment over the past few years, I would like to say that Fragment is indeed a smart design, but there are too many problems that need to be solved one by one when using Fragment, especially when processing data persistence.

First, although it has an onSaveInstanceState similar to the activity, do not rely on onSaveInstanceState to maintain data.

The following are some cases:

Scenario 1: rotate the screen when there is only one Fragment in the stack.

Yes, rotating the screen is the easiest way to keep test data. This situation is very simple. You only need to store the data that will be lost during rotation in the onSaveInstanceState storage, including the variables, and then retrieve the data in onActivityCreated or onViewStateRestored:

int someVar;@Overrideprotected void onSaveInstanceState(Bundle outState) {   outState.putInt("someVar", someVar);   outState.putString(“text”, tv1.getText().toString());}@Overridepublic void onActivityCreated(Bundle savedInstanceState) {   super.onActivityCreated(savedInstanceState);   someVar = savedInstanceState.getInt("someVar", 0);   tv1.setText(savedInstanceState.getString(“text”));}

It looks very simple, but there is such a situation that the View is rebuilt, but the onSaveInstanceState is not called, which means that everything on the UI is lost. Please refer to the following case.

Scenario 2:FragmentReturn from rollback Stack

When fragment is returned from the backstack (Fragment A here), the view in Fragment A is rebuilt according to the description of the Fragment lifecycle in the official document.

 

From this figure, we can see that when Fragment returns from the rollback stack,OnDestroyView and onCreateViewCalled,OnSaveInstanceStateIt seems that the interface has not been called, which leads to the returning of all UI data to the initial state defined in the xml layout. Of course, those views that implement state saving internally, such as EditText and TextView with the android: freezeText attribute, can still be maintained because Fragment can keep data for them, however, developers cannot obtain these events. We can only manually Save the data in onDestroyView.

The general process is as follows:

@ Overridepublic void onSaveInstanceState (Bundle outState) {super. onSaveInstanceState (outState); // save data here} @ Overridepublic void onDestroyView () {super. onDestroyView (); // If onSaveInstanceState is not called, data can be saved here}

But the question is, it is very easy to save data in onSaveInstanceState because it has the Bundle parameter, but onDestroyView does not. Where can it be saved? The answer is that it can coexist with Fragment.Argument.

The code is roughly as follows:

Bundle savedState; @ Overridepublic void onActivityCreated (Bundle savedInstanceState) {super. onActivityCreated (savedInstanceState); // Restore State Here if (! RestoreStateFromArguments () {// First Time running, Initialize something here }}@ Overridepublic void onSaveInstanceState (Bundle outState) {super. onSaveInstanceState (outState); // Save State Here saveStateToArguments () ;}@ Overridepublic void onDestroyView () {super. onDestroyView (); // Save State Here saveStateToArguments ();} private void saveStateToArguments () {savedState = saveState (); if (savedS Tate! = Null) {Bundle B = getArguments (); B. putBundle ("internalSavedViewState8954201239547", savedState) ;}} private boolean restoreStateFromArguments () {Bundle B = getArguments (); savedState = B. getBundle ("internalSavedViewState8954201239547"); if (savedState! = Null) {restoreState (); return true;} return false ;} /// // retrieves status data // /// // private void restoreState () {if (savedState! = Null) {// For example, // tv1.setText (savedState. getString ("text "));}} /// // save status data ///// /// // private Bundle saveState () {Bundle state = new Bundle (); // For example, // state. putString ("text", tv1.getText (). toString (); return state ;}

Now you can easilySaveState andrestoreStateData is stored and retrieved separately. Now it looks much better, almost succeeded, but there are more extreme cases.

 

Scenario 3: rotate more than one Fragment in the rollback stack twice

When you rotate the screen once, the onSaveInstanceState is called, and the UI status is saved as expected. However, when you rotate the screen again, the above Code may crash. The reason is that although onSaveInstanceState is called, When you rotate the screen, the Fragment view in the rollback stack will be destroyed and will not be rebuilt before the return. This leads to no view that can save data when you rotate the screen again.saveState()It will reference a non-existent view, leading to a null pointer exception NullPointerException. Therefore, you must first check whether the view exists. If the status data is saved, save the data in the Argument again, or simply do nothing, because it has been saved for the first time.

private void saveStateToArguments() {   if (getView() != null)      savedState = saveState();   if (savedState != null) {      Bundle b = getArguments();      b.putBundle(“savedState”, savedState);   }}


Final Fragment template:

The following is the fragment template I am using.

import android.os.Bundle;import android.support.v4.app.Fragment;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup; import com.inthecheesefactory.thecheeselibrary.R; /** * Created by nuuneoi on 11/16/2014. */public class StatedFragment extends Fragment {     Bundle savedState;     public StatedFragment() {        super();    }     @Override    public void onActivityCreated(Bundle savedInstanceState) {        super.onActivityCreated(savedInstanceState);        // Restore State Here        if (!restoreStateFromArguments()) {            // First Time, Initialize something here            onFirstTimeLaunched();        }    }     protected void onFirstTimeLaunched() {     }     @Override    public void onSaveInstanceState(Bundle outState) {        super.onSaveInstanceState(outState);        // Save State Here        saveStateToArguments();    }     @Override    public void onDestroyView() {        super.onDestroyView();        // Save State Here        saveStateToArguments();    }     ////////////////////    // Don't Touch !!    ////////////////////     private void saveStateToArguments() {        if (getView() != null)            savedState = saveState();        if (savedState != null) {            Bundle b = getArguments();            b.putBundle("internalSavedViewState8954201239547", savedState);        }    }     ////////////////////    // Don't Touch !!    ////////////////////     private boolean restoreStateFromArguments() {        Bundle b = getArguments();        savedState = b.getBundle("internalSavedViewState8954201239547");        if (savedState != null) {            restoreState();            return true;        }        return false;    }     /////////////////////////////////    // Restore Instance State Here    /////////////////////////////////     private void restoreState() {        if (savedState != null) {            // For Example            //tv1.setText(savedState.getString("text"));            onRestoreState(savedState);        }    }     protected void onRestoreState(Bundle savedInstanceState) {     }     //////////////////////////////    // Save Instance State Here    //////////////////////////////     private Bundle saveState() {        Bundle state = new Bundle();        // For Example        //state.putString("text", tv1.getText().toString());        onSaveState(state);        return state;    }     protected void onSaveState(Bundle outState) {     }}

If you use this template, you only need to inheritStatedFragmentClass and thenonSaveState()Save data,Retrieve Data in onRestoreState (), and the code above is ready for you. I believe it covers all the situations I know.

Library

Now the StatedFragment described in this article has been made into an easy-to-use library and released to the jcenter. Now you only need to add dependencies in build. gradle:

dependencies {    compile 'com.inthecheesefactory.thecheeselibrary:stated-fragment-support-v4:0.9.1'}

Inherits StatedFragment andonSaveState(Bundle outState)AndonRestoreState(Bundle savedInstanceState)Save and retrieve status data. If you want to do something when fragment is started for the first time, you can also rewrite it.OnFirstTimeLaunched (), which is called only at the first startup.

public class MainFragment extends StatedFragment {     ...     /**     * Save Fragment's State here     */    @Override    protected void onSaveState(Bundle outState) {        super.onSaveState(outState);        // For example:        //outState.putString("text", tvSample.getText().toString());    }     /**     * Restore Fragment's State here     */    @Override    protected void onRestoreState(Bundle savedInstanceState) {        super.onRestoreState(savedInstanceState);        // For example:        //tvSample.setText(savedInstanceState.getString("text"));    }     ... }

First-ever address http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0327/2648.html

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.