Android - salvar / restaurar o estado do fragmento

? Stanete @ | Original: StackOverFlow
---

Eu tenho uma atividade em que eu passar por vários fragmentos. Em cada fragmento Tenho várias visualizações ( EditText, ListView, mapa, etc).

Como posso salvar a instância do fragmento que é mostrado naquele momento? Eu preciso dele para trabalhar quando a atividade é onPause () -> onResume (). Também eu preciso dele para trabalhar quando eu voltar de outro fragmento ( pop de backstack ) .

Da actividade principal chamo o primeiro fragmento, em seguida, a partir do fragmento eu chamo a próxima.

Código para o meu Atividade:

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

Então aqui está o código para um dos meus fragmentos :

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

            });
        }}

Tenho pesquisado um monte de informações, mas nada claro . Alguém pode dar uma solução clara e um exemplo, por favor?

---

Top 5 Responder

1Raanan @

A fim de salvar o estado Fragmento você precisa implementar onSaveInstanceState() : "Além disso, como uma atividade, você pode manter o estado de um fragmento usando um Bundle, em caso de processo da atividade é morto e você precisa restaurar o estado do fragmento quando a atividade é recriada. Você pode salvar o estado durante onSaveInstanceState do fragmento () callback e restaurá-lo durante tanto onCreate (), onCreateView (), ou onActivityCreated (). Para obter mais informações sobre o estado de poupança, ver o documento Atividades ".

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

2cypressious @

Quando um fragmento é movido para a backstack, não é destruída . Todas as variáveis ​​de instância permanecer lá. Portanto, este é o lugar para salvar seus dados. Em onActivityCreated você verifique as seguintes condições:

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: Aqui está um exemplo

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 @

Você pode obter Fragmento atual gerente fragmento e se não deles em gerente fragmento você pode criar 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();
        }


    }


}

Também você pode usar setReatinInstance a verdade o que ele irá fazê-lo ignorar onDestroy método no fragmento e sua aplicação vai back ground e OS matar seu aplicativo para alocar mais memória que você vai precisar para salvar todos os dados que você precisa em pacote 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 @

Eu não tenho certeza se esta questão ainda está incomodando você, uma vez que tem sido vários meses. Mas eu gostaria de compartilhar como eu lidei com isso. Aqui está o código fonte:

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 aqui está o 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;
    }
}

O parentView é o ponto-chave . Normalmente, quando onCreateView, nós só usamos retorno rootView . Mas agora, eu adicionar rootView para parentView, e depois voltar parentView . Para evitar " A criança especificado já tem um pai . Você deve chamar removeView () no ... " erro, precisamos chamar " parentView.removeView ( rootView ) ", ou o método que eu fornecido é inútil. Eu também gostaria de compartilhar como eu encontrei. Em primeiro lugar, eu criar um booleano para indicar se a instância existe. Quando o exemplo existe, o rootView não será insuflado de novo . Mas, em seguida, logcat deu a criança já tem uma coisa pai, então eu decidi usar um outro pai como um pai intermediário View. É assim que funciona. Espero que seja útil para você.

5Sar @

Try this :

@Override
protected void onPause() {

    super.onPause();

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

@Override
protected void onResume() {

    super.onResume();

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

}

Espero que isso vai ajudar.

Além disso, você pode escrever para este tag atividade no arquivo menifest :

  android:configChanges="orientation|screenSize"

Good luck !!!