【问题标题】:Android activity navigation save stateAndroid活动导航保存状态
【发布时间】: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] 问题似乎在于向后导航和向上导航的不同行为。如果我向后导航,则活动将显示为其最后状态,而向上导航会强制重新创建活动。

【问题讨论】:

  • 你能发布活动完整代码吗?
  • 我的解决方案对你有用吗?

标签: android android-fragments navigation state


【解决方案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。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-28
  • 1970-01-01
相关资源
最近更新 更多