seguridad savedinstancestate restaurar practices example copia best activity android android-fragments fragment onresume back-stack

savedinstancestate - Android: guardar/restaurar el estado del fragmento



restaurar copia de seguridad whatsapp (7)

Como se indica aquí: ¿Por qué usar Fragment # setRetainInstance (boolean)?

también puedes usar el método de fragmentos setRetainInstance(true) esta manera:

public class MyFragment extends Fragment { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // keep the fragment and all its data across screen rotation setRetainInstance(true); } }

Tengo una actividad en la que reviso varios fragmentos. En cada fragmento tengo varias vistas ( EditText, ListView, Map , etc.).

¿Cómo puedo guardar la instancia del fragmento que se muestra en ese momento? Necesito que funcione cuando la actividad es onPause() --> onResume() . También necesito que funcione cuando regrese de otro fragmento (pop de backstack).

De la Activity principal llamo al primer fragmento, luego del fragmento al que llamo el siguiente.

Código para mi actividad:

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

Entonces aquí está el código para uno de mis 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(); }); }}

He buscado mucha información, pero nada claro. ¿Alguien puede dar una solución clara y un ejemplo, por favor?


Cuando un fragmento se mueve a la backstack, no se destruye. Todas las variables de instancia permanecen allí. Este es el lugar para guardar sus datos. En onActivityCreated , comprueba las siguientes condiciones:

  1. ¿Es el paquete! = Nulo? En caso afirmativo, ahí es donde se guardan los datos (probablemente cambie la orientación).
  2. ¿Hay datos guardados en variables de instancia? En caso afirmativo, restaure su estado (o quizás no haga nada, porque todo es como debería ser).
  3. De lo contrario, tu fragmento se muestra por primera vez, crea todo de nuevo.

Editar: Aquí hay un ejemplo

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


Fragmento de Android tiene algunas ventajas y algunas desventajas. La mayor desventaja del fragmento es que cuando quieres usar un fragmento lo creas. Cuando lo usa, se onCreateView del fragmento cada vez. Si desea mantener el estado de los componentes en el fragmento, debe guardar el estado del fragmento y debe cargar su estado en el siguiente. Esto hace que la vista de fragmento sea un poco lenta y rara.

Encontré una solución y utilicé esta solución: "Todo es genial. Todos pueden intentarlo".

La primera vez que se ejecuta onCreateView , cree la vista como una variable global. Cuando onCreateView llamar a este fragmento en onCreateView nuevamente, puede devolver esta vista global. El estado del componente del fragmento se mantendrá.

View view; @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { setActionBar(null); if (view != null) { if ((ViewGroup)view.getParent() != null) ((ViewGroup)view.getParent()).removeView(view); return view; } view = inflater.inflate(R.layout.mylayout, container, false); }


No estoy seguro de si esta pregunta todavía te molesta, ya que han pasado varios meses. Pero me gustaría compartir cómo lidié con esto. Aquí está el código fuente:

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

Y aquí está la actividad principal:

/** * 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; } }

parentView es el punto clave. Normalmente, cuando onCreateView , simplemente utilizamos return rootView . Pero ahora, agrego rootView a parentView , y luego devuelvo parentView . Para evitar "El hijo especificado ya tiene un padre. Debe llamar a removeView() en el ..." error, necesitamos llamar a parentView.removeView(rootView) , o el método que proporcioné es inútil. También me gustaría compartir cómo lo encontré. En primer lugar, configuré un booleano para indicar si existe la instancia. Cuando existe la instancia, la vista rootView no se volverá a inflar. Pero entonces, logcat le dio al niño que ya tiene algo de padre, así que decidí usar otro padre como una Vista de padres intermedia. Asi es como funciona.

Espero que sea útil para ti.


Para guardar el estado de Fragment necesita implementar onSaveInstanceState() : "También como una actividad, puede retener el estado de un fragmento usando un Bundle, en caso de que se mate el proceso de la actividad y necesite restaurar el estado del fragmento cuando el Se puede volver a crear la actividad. Puede guardar el estado durante la devolución de llamada onSaveInstanceState() del fragmento y restaurarlo durante onCreate() , onCreateView() o onActivityCreated() . Para obtener más información sobre cómo guardar el estado, consulte el documento de Actividades.

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


Prueba esto :

@Override protected void onPause() { super.onPause(); if (getSupportFragmentManager().findFragmentByTag("MyFragment") != null) getSupportFragmentManager().findFragmentByTag("MyFragment").setRetainInstance(true); } @Override protected void onResume() { super.onResume(); if (getSupportFragmentManager().findFragmentByTag("MyFragment") != null) getSupportFragmentManager().findFragmentByTag("MyFragment").getRetainInstance(); }

Espero que esto ayude

También puede escribir esto en la etiqueta de actividad en el archivo de menifest:

android:configChanges="orientation|screenSize"

Buena suerte !!!


Puedes obtener el Fragmento actual de fragmentManager. Y si no hay ninguno en el administrador de fragmentos, puedes crear 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(); } } }

también puedes usar setRetainInstance en true lo que hará es ignorar el método onDestroy() en fragmento y tu aplicación irá a segundo onDestroy() y te matará la aplicación para asignar más memoria que necesitarás para guardar todos los datos que necesitas en el paquete 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 onRestoreInstanceState(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"); } }