繁体   English   中英

在 Activity 中保存片段状态

[英]Saving fragment state in Activity

当我尝试在主要活动中保存片段的状态时,出现以下错误:

java.lang.IllegalStateException: Fragment MarketviewFragment{c5e0f0d} is not currently in the FragmentManager
    at androidx.fragment.app.FragmentManagerImpl.putFragment(FragmentManager.java:923)
    at com.shoob.capstone.android.crypfolio.MainActivity.onSaveInstanceState(MainActivity.java:308)
    at android.app.Activity.performSaveInstanceState(Activity.java:1608)
    at android.app.Instrumentation.callActivityOnSaveInstanceState(Instrumentation.java:1443)
    at android.app.ActivityThread.callActivityOnSaveInstanceState(ActivityThread.java:5038)
    at android.app.ActivityThread.callActivityOnStop(ActivityThread.java:4372)
    at android.app.ActivityThread.handleRelaunchActivityInner(ActivityThread.java:4986)
    at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4922)
    at android.app.servertransaction.ActivityRelaunchItem.execute(ActivityRelaunchItem.java:69)
    at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
    at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1926)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:214)
    at android.app.ActivityThread.main(ActivityThread.java:6986)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)

在我的主要活动中,我有 4 个可能的片段,一次只显示一个。 我保留对主要活动中的片段的引用,并根据需要显示它们:

private MarketviewFragment marketviewFragment;
private WatchlistFragment watchlistFragment;
private PortfolioFragment portfolioFragment;
private DetailsFragment detailsFragment;

我使用以下代码设置当前显示的片段(一次只显示一个片段):

//fragment is an instance of one of the 4 types of fragments above
private void setFragment(Fragment fragment) {
    FragmentManager fm = getSupportFragmentManager();

    if (fm.findFragmentById(R.id.frag_main) != null) {
        fm.beginTransaction()
                .replace(R.id.frag_main, fragment)
                .commit();
    } else {
        fm.beginTransaction()
                .add(R.id.frag_main, fragment)
                .commit();
    }
}

这是我设置每个片段的方式(一个示例,其他类型相同):

private void setPortfolioFragment() {
    if (portfolioFragment == null) {
        portfolioFragment = PortfolioFragment.newInstance();
    }
    setFragment(portfolioFragment);
}

现在我的问题。 如何保存所有这些片段的状态? 我想将它们全部保存在一个 Bundle 中,这样我就可以在重新创建 Main Activity 时恢复它们(例如在旋转时)。

我现在这样做的方式似乎不起作用,这样做的正确方法是什么?

保存状态:

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);

    if (marketviewFragment != null) {
        getSupportFragmentManager().putFragment(outState, KEY_BUNDLE_MARKETVIEW_FRAGMENT, marketviewFragment);
    }
    if (watchlistFragment != null) {
        getSupportFragmentManager().putFragment(outState, KEY_BUNDLE_WATCHLIST_FRAGMENT, watchlistFragment);
    }
    if (portfolioFragment != null) {
        getSupportFragmentManager().putFragment(outState, KEY_BUNDLE_PORTFOLIO_FRAGMENT, portfolioFragment);
    }
    if (detailsFragment != null) {
        getSupportFragmentManager().putFragment(outState, KEY_BUNDLE_DETAILS_FRAGMENT, detailsFragment);
    }

}

恢复状态:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    if (savedInstanceState != null) {
        marketviewFragment = (MarketviewFragment)getSupportFragmentManager().getFragment(savedInstanceState, KEY_BUNDLE_MARKETVIEW_FRAGMENT);
        watchlistFragment = (WatchlistFragment)getSupportFragmentManager().getFragment(savedInstanceState, KEY_BUNDLE_WATCHLIST_FRAGMENT);
        portfolioFragment = (PortfolioFragment)getSupportFragmentManager().getFragment(savedInstanceState, KEY_BUNDLE_PORTFOLIO_FRAGMENT);
        detailsFragment = (DetailsFragment)getSupportFragmentManager().getFragment(savedInstanceState, KEY_BUNDLE_DETAILS_FRAGMENT);

    }
}

每次分离片段时都应该保存它。 也请在fragmentManager上使用分离/附加而不是replace

另一件事是FragmentManager应该自己恢复片段。 我个人会用FragmentPagerAdapter来做,然后只切换可见的。

最好和最简单的方法是将所有片段附加到 FragmentManager,并控制可见性。 由于保存/恢复将自动完成

您的活动不应为每个片段处理保存状态。 您应该通过覆盖每个片段类中的 onSaveInstanceState() 来让每个片段处理存储自己的状态:

@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
    super.onSaveInstanceState(outState);
    // save fragment state here
}

此外,在您的活动中保留对所有片段的硬引用并不是一个好主意。

编辑:再次查看您的问题后,我更了解您要做什么。 您正在尝试保存和恢复片段的实际实例。 Android 操作系统会自动为您执行此操作,而您正试图妨碍此过程。 同样,您将片段存储为实例变量这一事实是问题的一部分,并且让您做一些通常不需要做的事情。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM