[英]How to Restore ViewPager from savedInstanceState
所以我有一個我似乎無法解決的問題。 我在其中一項活動中有一個ViewPager,比如MainActivity 。 當活動在后台被殺死時,我正在實現保存和檢索實例狀態所需的所有方法。 但是當活動嘗試恢復其狀態時,片段將被恢復,但它們不會附加到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
在后台被殺死(我使用Do not Keep Activities設置來測試它),會發生這種情況:
1)活動正確恢復,沒有問題。
2)調用片段的onCreateView
,且savedInstanceState
保持不變。
3)但是,我的Activity中的ViewPager和Adapter是null
。 片段似乎沒有附加到適配器/ viewpager。
那我在這里錯過了什么? 我應該做些什么來正確恢復碎片嗎?
我可以通過在MainActivity
替換它來快速解決問題:
if (savedInstanceState==null) {
setupViewPager();
}
只需setupViewPager();
,以便創建新的適配器和片段,無論它是第一次還原還是啟動。 但這帶來了重置片段狀態的缺點。 此外,當我這樣做時,我發現每個片段有兩個實例,一個是恢復的,另一個是新實例,只實際顯示了新實例。 所以我不相信這是最好的方法。
通過銷毀Activity
您還會銷毀每個實例字段。 所以你必須重新實例化ViewPager
和Adapter
。 您必須記住兩種情況。
FragmentStatePagerAdapter
保存/恢復Fragments
與FragmentManager
Fragments
內Fragment
第一點是每個Fragment
有兩個實例的原因。 為了解決這個問題,您可以通過其ID獲取存儲的Fragment。 看到這個 grepcode FragmentPagerAdapter
(同樣適用於StateAdapter
)
private static String makeFragmentName(int viewId, int index) {
return "android:switcher:" + viewId + ":" + index;
}
而不是每次都在setupViewPager
中實例化Fragment
- 你首先從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");
}
以上是如何從FragmentManager
恢復以前保存的Fragments
的示例。 您可能需要調整具有不同類型BaseFragments
,依此類推。 此外,您可能希望保存Fragment
標題名稱和總計數以還原它們。
第二點是你必須從Fragment
本身恢復當前的Fragment
狀態。 為此,您的Fragment
具有生命周期方法。 請參閱此SO主題關於一勞永逸,如何在后端堆棧中正確保存Fragments的實例狀態?
FragmentStatePagerAdapter具有saveState()和restoreState()方法來保存和恢復它的狀態。
saveState:保存與此適配器關聯的任何實例狀態及其在需要重建當前UI狀態時應恢復的頁面。
因此,似乎可以使用這些方法來存檔您的目標。 對不起,我現在沒有編譯器,所以我無法測試下面的代碼。
@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);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.