点击子Activity Up按钮时父Activity savedInstanceState为null问题咨询
我之前开发时也碰到过几乎一模一样的场景,太懂这种明明按了返回却发现页面状态全丢的头疼了!咱们先搞清楚问题出在哪,再一步步解决。
问题根源
默认情况下,点击Up按钮(也就是ActionBar上的返回箭头),系统会启动一个新的父Activity实例(也就是你的Activity A),而不是回到之前已经存在的那个实例。这就导致新创建的A的savedInstanceState自然是null——因为它是全新的,根本没有之前的状态可以恢复。
具体解决方案
咱们分几步来调整,确保点击Up按钮时能回到原来的A实例,并且保留状态:
1. 先确认Manifest里的父Activity配置(基础)
首先要保证在AndroidManifest.xml里正确给Activity B指定父Activity,这样系统才知道Up按钮该指向哪个页面:
<activity android:name=".ActivityB" android:parentActivityName=".ActivityA"> <!-- 兼容Android 4.0及以下版本 --> <meta-data android:name="android.support.PARENT_ACTIVITY" android:value=".ActivityA" /> </activity>
2. 给Activity A设置singleTop启动模式
在Manifest里给Activity A加上android:launchMode="singleTop",这样当从B返回时,系统会复用已经在栈顶的A实例,而不是新建一个:
<activity android:name=".ActivityA" android:launchMode="singleTop"> <!-- 其他配置 --> </activity>
3. 重写Activity A的onNewIntent方法
因为当A被singleTop模式复用时,不会重新调用onCreate,而是触发onNewIntent。这里你需要重新获取topicId,并刷新任务列表(如果B修改了任务数据,还需要重新查询SQLite):
@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); // 更新当前的Intent为新传入的Intent setIntent(intent); // 重新获取topicId if (getIntent() != null) { int topicId = getIntent().getIntExtra("topicId", -1); if (topicId != -1) { // 这里重新从SQLite查询对应分类的任务列表,刷新UI loadTasksByTopicId(topicId); } } }
4. (可选)手动处理Activity B的Up按钮点击
如果上面的配置还没解决问题,你可以直接在Activity B里重写Up按钮的点击逻辑,让它直接finish()回到原来的A实例,而不是让系统启动新的:
@Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { // 直接关闭当前Activity,回到栈里的上一个Activity(也就是原来的A) finish(); return true; } return super.onOptionsItemSelected(item); }
额外提醒
如果你的Activity A在后台被系统回收了,那savedInstanceState还是会为null,这时候你需要在A的onCreate里先从Intent中获取topicId,而不是完全依赖savedInstanceState:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_a); int topicId = -1; // 优先从Intent获取topicId,再考虑savedInstanceState if (getIntent() != null) { topicId = getIntent().getIntExtra("topicId", -1); } else if (savedInstanceState != null) { topicId = savedInstanceState.getInt("topicId", -1); } if (topicId != -1) { loadTasksByTopicId(topicId); } } // 记得保存topicId到savedInstanceState,以防Activity被回收 @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putInt("topicId", yourTopicIdVariable); }
这样调整后,点击Up按钮返回时,就能回到原来的Activity A实例,既保留了状态,也能正确展示对应分类的任务列表啦!
内容的提问来源于stack exchange,提问作者castafiore

