当前位置: 首页 > 知识库问答 >
问题:

如何从savedInstanceState恢复ViewPager

经嘉
2023-03-14

所以我有一个我似乎无法解决的问题。我有一个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);
    }
}
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在后台被杀死(我使用Don't Keep Activities设置来测试它),就会发生这样的情况:

1)活动已正确还原,没有任何问题。
2)片段的onCreateView已调用,SavedInstanceState未损坏。
3)但是,我的活动中的ViewPager和适配器都为Null。片段似乎没有连接回适配器/ViewPager。

那我错过了什么?我应该做些什么来恢复碎片吗?

通过在我的mainactivity中替换此内容,可以快速解决此问题:

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

只使用setupviewpager();,这样就可以创建新的适配器和片段,而不管它是还原还是首次启动。但这会带来一个缺点,即重置片段的状态。而且,当我这样做时,我发现每个片段有两个实例,一个是还原的,一个是新的,只有新的实例实际显示。所以我不认为这是最好的方法。

共有1个答案

戴原
2023-03-14

通过销毁activity,您还会销毁每个实例字段。因此您必须重新实例化ViewPagerAdapter。有两种情况你必须记住。

  1. FragmentStatePagerAdapter使用FragmentManager
  2. 保存/还原 片段
  3. 您必须还原片断片断的状态

第一点是每个fragment都有两个实例的原因。为了解决这个问题,您可以通过其ID获取存储的片段。请参阅此grepcodeFragmentPagerAdapter(对于StateAdapter)

private static String makeFragmentName(int viewId, int index) {
    return "android:switcher:" + viewId + ":" + index;
}

而不是每次都在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");
}

上面是关于如何从FragmentManager还原以前保存的片段的示例。您可能必须调整具有不同类型的baseFragments等等的情况。此外,您可能希望保存fragment标题名和总数,以还原它们。

第二点是您必须从片段本身恢复当前片段状态。因此,您的fragment具有生命周期方法。看一下这个主题,如何正确保存后堆栈中片段的实例状态?

 类似资料:
  • 我有一个活动,它为结果启动了一些其他活动,所以当结果回来时,该活动可能已经或可能没有被销毁和重新创建。 我已经重写了onSaveInstanceState,以便添加需要保留和恢复的数据。 当活动被销毁并重新创建时,onCreate被传递给savedInstanceState包;但也调用并传递了相同的捆绑包onRestoreInstanceState()。 那么我应该把从捆绑包中提取数据并恢复状态的

  • 问题内容: 我获得了一个MySQL数据库文件,需要将其还原为Windows Server 2008计算机上的数据库。 我尝试使用MySQL Administrator,但出现以下错误: 所选文件是由mysqldump生成的,不能由该应用程序还原。 我该如何工作? 问题答案: 它应该像运行此命令一样简单: 如果转储是单个数据库,则可能必须在文件顶部添加一行: 如果它是许多数据库的转储,则use语句已

  • 如何恢复连接?希望不完全重新安装我的postgres?? 非常感谢:)

  • 问题内容: 我正在研究6B小文档的ES群集,这些文档以6.5K索引进行组织,总共6TB。索引在7台服务器之间复制和分片。索引占用量从几KB到几百GB不等。 在使用ES之前,我将Lucene与相同的文档组织一起使用。 基于Lucene的应用程序 的恢复 非常迅速 。实际上,当查询到达时,索引是延迟加载的,然后将IndexReader缓存起来,以加快以后的回复速度。 现在, 使用Elasticsear

  • 我正在为一个Cassandra数据库构建一个备份和恢复过程,以便在我需要的时候做好准备,这样我就可以理解细节,以便构建适合生产的东西。我在这里遵循Datastax的说明: http://www.datastax.com/documentation/cassandra/2.0/cassandra/operations/ops_backup_restore_c.html。 首先,我将数据库放置在一个d

  • 问题内容: 我想知道是否有可能恢复我之前转换为字节数组的RSA公钥。 谢谢您的帮助。 问题答案: 有关更多信息,请参阅本教程