Android - сохранить / восстановить состояние фрагмент

? Stanete @ | Original: StackOverFlow
---

У меня есть деятельность, в которой я иду через несколько фрагментов. В каждом фрагменте меня есть несколько мнений ( EditText, ListView, карта, и т.д.).

Как я могу сохранить экземпляр фрагмента, который показан в тот момент? Мне нужно работать, когдадеятельность OnPause () -> onResume (). Также мне нужно работать, когда я возвращаюсь из другого фрагмента (POP от backstack ) .

От основной деятельности я называю первый фрагмент, то из фрагмента я называю следующий.

Код для моей деятельности :

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

Тогда воткод для одного из моих фрагментов :

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

            });
        }}

Я искал много информации, но ничего не ясно. Может кто-нибудь дать четкое решение и пример, пожалуйста?

---

Top 5 ответ

1Raanan @

Для того, чтобы сохранить фрагмент состояние необходимое для реализации onSaveInstanceState() : " Кроме того, как упражнение, вы можете сохранить состояние фрагмента с помощью Bundle, в случае процесс деятельности является убил, и вы должны восстановить состояние фрагмент, когдадеятельность заново. Вы можете сохранить состояние во время onSaveInstanceState фрагмента () Обратный звонок и восстановить его во время или OnCreate (), onCreateView (), или onActivityCreated (). Для получения более подробной информации о сохранении государства, увидеть документ Спорт " .

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

2cypressious @

Когда фрагмент перемещается в backstack, она не разрушается . Все переменные экземпляра остаются там . Так что этоместо, чтобы сохранить ваши данные. В onActivityCreated вы проверьте следующие условия :

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.

Изменить: Вотпример

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 @

Вы можете получить текущий фрагмент от менеджера фрагмента и, если оно не из них в диспетчере фрагментов Вы можете создать 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();
        }


    }


}

Также вы можете использовать setReatinInstance к истине, что он будет делать это игнорировать OnDestroy метод в фрагменте и ваше приложение собирается отступать землю и OS убить вашу заявку на выделение дополнительной памяти вам будет нужно сохранить все данные, необходимые в 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 @

Я не совсем уверен, что если этот вопрос до сих пор беспокоит вас, так как уже несколько месяцев . Но я хотел бы поделиться, как я справлялся с этим . Вотисходный код :

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

А вот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;
    }
}

ParentView являетсяKeypoint . Обычно, когда onCreateView, мы просто используем обратный rootView . Но теперь, я добавляю rootView в parentView, а затем вернуться parentView . Для предотвращения "указано ребенок уже имеет родителя . Вы должны позвонить removeView () на ... " ошибки, мы должны называть " parentView.removeView ( rootView )", илиметод, который я поставляется бесполезно. Я также хотел бы поделиться, как я нашел его. Во-первых, я создал логическое чтобы указать, еслиэкземпляр не существует. Когдаэкземпляр существует,rootView не будет завышена снова. Но тогда, LogCat далребенок уже имеет родительский вещь, поэтому я решил использовать другой родитель в промежуточной родительского вида . Вот как это работает. Надеюсь, что это полезно для вас.

5Sar @

Try this :

@Override
protected void onPause() {

    super.onPause();

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

@Override
protected void onResume() {

    super.onResume();

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

}

Надеюсь, что это поможет.

Также вы можете написать об этом теге деятельности в menifest файла :

  android:configChanges="orientation|screenSize"

Good luck !!!