java - 如何从 savedInstanceState 恢复 ViewPager

标签 java android performance android-fragments android-viewpager

所以我有一个我似乎无法解决的问题。我的一个 Activity 中有一个 ViewPager,比如 MainActivity。当 Activity 在后台被杀死时,我正在实现所有必需的方法来保存和检索实例状态。但是当 Activity 试图恢复它的状态时, fragment 被恢复但它们没有附加到 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;
}

因此,如果我导航到另一个 Activity ,然后 MainActivity 在后台被杀死(我正在使用 Don’t Keep Activities 设置来测试它),就会发生这种情况:

1) Activity 已正确恢复,没有问题。
2) 调用 fragment 的onCreateViewsavedInstanceState保持不变。
3) 但是,我的 Activity 中的 ViewPager 和 Adapter 是 null。这些 fragment 似乎没有连接回适配器/viewpager。

那么我在这里缺少什么?我应该做些什么来正确恢复 fragment 吗?

附言:

我可以通过在我的 MainActivity 中替换它来快速解决问题:

if (savedInstanceState==null) {
    setupViewPager();
}

仅使用 setupViewPager();,这样无论是恢复还是首次启动,都会创建新的适配器和 fragment 。但这伴随着重置 fragment 状态的缺点。此外,当我这样做时,我发现每个 fragment 都有两个实例,一个是恢复的,一个是新的,实际只显示新实例。所以我不认为这是最好的方法。

最佳答案

通过销毁 Activity,您还销毁了每个实例字段。所以你必须重新实例化 ViewPagerAdapter。您必须牢记两种情况。

  1. FragmentStatePagerAdapter 使用 FragmentManager 保存/恢复 Fragments
  2. 您必须恢复 Fragment 中的 Fragments 的状态

第一点是每个Fragment 有两个实例的原因。为了解决这个问题,您可以通过 ID 获取存储的 fragment 。 See this 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 具有生命周期方法。请参阅有关 Once for all, how to correctly save instance state of Fragments in back stack? 的 SO 主题

关于java - 如何从 savedInstanceState 恢复 ViewPager,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47108494/

相关文章:

java - Web服务调用时如何拦截xml响应和请求?

android - 为什么 Sync-Gateway 显示 "404 no such database"错误?

android - 如何正确设置 UiAutomatorViewer 来检查用于使用 Appium 测试 Android 应用程序的元素?

JavaScript 最佳实践 - 全局变量

c++ - SSE42 & STTNI - PcmpEstrM 比 PcmpIstrM 慢两倍,这是真的吗?

java - 如何在 Java 程序中检查 Unix 凭据

java - HttpClient:确定响应中的空实体

Java 连接被拒绝

android - 如何将 AppCompatActivity 与 Fabric 一起使用来获取时间轴?

Python - 提高我的算法速度