Android活动导航保存状态

Posted

技术标签:

【中文标题】Android活动导航保存状态【英文标题】:Android activity navigation save state 【发布时间】:2014-02-24 01:37:34 【问题描述】:

在主要活动ActivityA 中,我将FragmentA 替换为片段FragmentB。从FragmentB,用户可以开始一个新的活动ActivityB。通过点击ActivityB 中的返回按钮,ActivityA 将显示为FragmentA。我期待看到FragmentB 的最后状态。我是否必须单独保存以前活动的状态才能提供此行为?

ActivityA(FragmentA) -> ActivityA(FragmentB) -> ActivityB 
BACK
ActivityA(FragmentB)

在主要活动中,我使用以下方式设置当前片段:

FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
               .replace(R.id.a_main_frame_content, new FragmentB())
               .addToBackStack(null)
               .commit();

从片段中我开始一个新的活动:

Intent intent = new Intent(getActivity(), ActivityB.class);
getActivity().startActivity(intent);

ActivityA 被设置为ActivityB 的父活动以提供正确的导航。

[UPDTATE] 问题似乎在于向后导航和向上导航的不同行为。如果我向后导航,则活动将显示为其最后状态,而向上导航会强制重新创建活动。

【问题讨论】:

你能发布活动完整代码吗? 我的解决方案对你有用吗? 【参考方案1】:

让我们试试这个:

在parentActivity的intent中(如果你可以在创建parentActivity之前设置它最好,否则你可能不得不使用setIntent):

    currentActivityIntent.putExtra("random-unique-key-for-each-activity",
random-unique-key-for-each-activity);

在您创建子活动之前,您将以下内容放入地图中:

myKeyIntentMap.put(random-unique-key-for-each-activity, currentActivityIntent);

在“Up”事件触发的方法中:


String parentKey = currentActivity.parentActivity.getIntent.getStringExtra("random-unique-key-for-each-activity");
Intent intentToLaunch = (Intent)myKeyIntentMap.get(parentKey);
intentToLaunch.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_SINGLE_TOP );
startActivity(intentToLaunch);

这样,使用意图,即使您的历史堆栈是 A-someAct1-someAct2-B,并且您启动解析到 A 的意图,它也会被“带到前面”杀死一些行为。

附:我没有做任何空检查,也没有记住确切的方法名称,只是给了你一个方法。

【讨论】:

这实际上可以工作。但我想我误解了设计指南。通过执行这样的操作,UP 按钮的行为将无法达到预期。 IMO 你要求一些不可接受的东西,上一个屏幕并不意味着它必须重新加载屏幕。意图标志用于将现有行为置于前面或启动新行为等,因此这完全取决于它如何适合您的应用程序。如果 UP 需要保留父活动的先前状态,则可以使用我的解决方案,否则请使用他们提供的解决方案。但理想情况下,我喜欢一个选项来指定,如果我想去以前的状态或新的状态。【参考方案2】:

“向上”的行为有时确实具有误导性。当我遇到类似的问题时,我更愿意节省时间而不是处理保存状态。 您可以通过在Activity 中捕获导航“向上”事件来快速解决它:

@Override
public boolean onOptionsItemSelected(MenuItem item) 
    if (item.getItemId() == android.R.id.home) 
        onBackPressed();
    
    return true;

【讨论】:

有没有办法判断backstack中是否有activity?如果我的应用程序直接在这个 Activity 中启动,我该怎么办? 好吧,我认为你不必这样做。使用此代码,一切都将按预期工作:当您按下返回或向上处于最后一个返回堆栈状态(活动或片段)时,您将离开 app.框架将为您完成所有工作。试试看。 有没有办法说:If up-activity == back-activty then onBackPressed() 你为什么需要它?据我所知 up-activity 总是等于 back-activty。 不,这不是真的。 Up 始终指向活动的逻辑父级,而 back 指向查看的最后一个活动。向上与向后:developer.android.com/design/patterns/navigation.html【参考方案3】:

发生这种情况是因为当您移动到 ​​ActivityB 时,activityA 将分别关闭和销毁状态,因此当您返回到活动 ActivityA 时,ActivityA 再次开始,因此您将 fragmentA 作为视图。您需要使用 sharedPfer 保存状态。使用一些标志将状态保存在onCreateView() 检查状态并为视图设置正确的片段。希望你明白我的意思。

public static final String PREFS_NAME = "mypref";
boolean isVisited;
//check sharedpref
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
 isVisited= settings.getBoolean("isVisited", false);

if(!isVisited)
// set fragmentA
else 
// set fragmentB



// inside fragment transaction block

Editor edit = settings.editor();
isVisited.setBoolean(true);
edit.commit();

【讨论】:

感谢提示,知道了。但这是否也意味着我也必须保存片段视图的状态?喜欢 ListView 的数据和滚动位置? 如果你想显示特定的,那么你也可以保存这些状态。 @Yup 当我们将活动 A 移动到 B 时,它调用活动 A 的 OnPause 和 OnStop 而不是 OnDestroy。

以上是关于Android活动导航保存状态的主要内容,如果未能解决你的问题,请参考以下文章

保存/恢复android webview的状态

如何保存底部导航片段的状态 - 具有单个导航图的 Android 导航组件

Android导航组件:如何保存片段状态

如何保存android活动的状态

Android 全屏片段不显示导航和状态栏后面的元素

Android - 在不同活动之间切换时保存当前的 onCreate 状态