Как восстановить ViewPager из savedInstanceState
Итак, у меня проблема, которую я не могу решить. У меня есть ViewPager в одном из моих занятий, скажем MainActivity. Я реализую все необходимые методы для сохранения и извлечения состояния экземпляра, когда действие убивается в фоновом режиме. Но когда activity пытается восстановить свое состояние, фрагменты восстанавливаются, но они не прикреплены к viewpager, поэтому все, что я получаю, это белый экран.
вот код, соответствующий :
MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//..
if (savedInstanceState==null) {
setupViewPager();
}
}
private void setupViewPager() {
mAdapter = new ViewPagerAdapter(getSupportFragmentManager());
mAdapter.addFrag(FirstFragment.newInstance(mFeedItem), "INFO");
//Note: mFeedItem is obtained from the intent and I have verified
// that it is properly restored.
mAdapter.addFrag(SecondFragment.newInstance(mFeedItem), "SERVICES");
mViewPager.setAdapter(mAdapter);
mTabLayout.setupWithViewPager(mViewPager);
}
ViewPagerAdapter.java
public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private final List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) {
super(manager);
}
@Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
@Override
public int getCount() {
return mFragmentList.size();
}
public void addFrag(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
@Override
public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position);
}
}
FirstFragment.java
public static FirstFragment newInstance(Workshop item) {
FirstFragment f = new FirstFragment();
f.mItem = item;
return f;
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("feed_item",Workshop.packToGson(mItem));
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_item_detail_info, container, false);
if (savedInstanceState!=null) {
mItem = Workshop.extractGson(savedInstanceState.getString("feed_item"));
}
return v;
}
поэтому, если я перейду к другому действию, а затем MainActivity
убит в фоновом режиме ( я использую не держите деятельность настройка для проверки этого), это происходит:
1) Активность восстанавливается должным образом, никаких проблем нет.
2) The onCreateView
из фрагментов называются, с savedInstanceState
нетронутыми.
3) но, ViewPager и адаптер в моей деятельности являются null
. Фрагменты, похоже, не прикрепляются обратно к адаптеру/viewpager.
так что я упускаю здесь? Я должен что-то сделать, чтобы восстановить фрагменты?
PS:
я могу быстро решить проблему, заменив это в моем MainActivity
:
if (savedInstanceState==null) {
setupViewPager();
}
С setupViewPager();
, так что новый адаптер и фрагменты создаются независимо от того, восстанавливается ли он или запускается в первый раз. Но это связано с недостатком сброса состояния фрагментов. Кроме того, когда я это делаю, я нахожу, что есть два экземпляра каждого фрагмента, один из которых восстанавливается и новый, с отображением только новых экземпляров. Поэтому я не считаю, что это лучший подход.
2 ответов
уничтожить Activity
вы также уничтожаете каждое поле экземпляра. Таким образом, вы должны повторно создать экземпляр ViewPager
и Adapter
. Есть два сценария, которые вы должны иметь в виду.
-
FragmentStatePagerAdapter
сохраняет/восстанавливаетFragments
СFragmentManager
- вы должны восстановить состояние
Fragments
внутриFragment
первый момент-причина, по которой у вас есть два экземпляра каждого Fragment
. Чтобы исправить это, вы можете получить сохраненный Фрагмент его ID. посмотреть этот grepcode FragmentPagerAdapter
(то же самое для StateAdapter
)
private static String makeFragmentName(int viewId, int index) {
return "android:switcher:" + viewId + ":" + index;
}
вместо создания Fragment
на setupViewPager
каждый раз - вы получаете его от FragmentManager
во-первых, например,
mAdapter = new ViewPagerAdapter(getSupportFragmentManager());
int fragmentCount = 2; // save value if it's a arbitrary list of fragments
for (int index = 0; i < fragmentCount; i++) {
FirstFragment firstFragment = (FirstFragment) getSupportFragmentManager().findFragmentByTag(makeFragmentName(R.id.view_pager, index));
if (firstFragment == null) {
firstFragment = FirstFragment.newInstance(mFeedItem);
}
mAdapter.addFrag(firstFragment, "someTitle");
}
выше приведен пример того, как восстановить предыдущие сохраненные Fragments
С FragmentManager
. Вероятно, вам придется настроить случаи, когда у вас есть разные типы BaseFragments
и так далее. Кроме того, вы можете сохранить Fragment
названия и общее количество для их восстановления.
второй момент заключается в том, что вы должны восстановить ток Fragment
государство от . За что ваш Fragment
есть методы жизненного цикла. См. эту тему SO об этом раз и навсегда, Как правильно сохранить состояние экземпляра фрагментов в задней стеке?
FragmentStatePagerAdapter имеет метод saveState () и restoreState () для сохранения и восстановления его состояния..
saveState: сохраните любое состояние экземпляра, связанное с этим адаптером и его страницами, которые должны быть восстановлены, если необходимо восстановить текущее состояние пользовательского интерфейса.
Так кажется, что можно было бы используйте эти методы, чтобы достичь цели. Извините, но у меня сейчас нет компилятора, поэтому я не мог протестировать код ниже.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
setupViewPager(savedInstanceState);
}
}
private void setupViewPager(Bundle savedInstanceState) {
mAdapter = new ViewPagerAdapter(getSupportFragmentManager());
if (savedInstanceState != null) {
Parcelable parcelable = savedInstanceState.getParcelable("Adapter");
mAdapter.restoreState(parcelable, getClassLoader());
} else {
mAdapter.addFrag(FirstFragment.newInstance(mFeedItem), "INFO");
//Note: mFeedItem is obtained from the intent and I have verified
// that it is properly restored.
mAdapter.addFrag(SecondFragment.newInstance(mFeedItem), "SERVICES");
}
mViewPager.setAdapter(mAdapter);
mTabLayout.setupWithViewPager(mViewPager);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Parcelable parcelable = mAdapter.saveState();
outState.putParcelable("Adapter", parcelable);
}