简体   繁体   English

savedInstanceState 始终为 null

[英]savedInstanceState is always null

This is my savedInstaceState code:这是我的 savedInstaceState 代码:

@Override
public void onSaveInstanceState(Bundle savedInstanceState) 
{
    savedInstanceState.putStringArrayList("todo_arraylist", Altodo);
    Log.v("bundle", "Saved");
    super.onSaveInstanceState(savedInstanceState);
}


public void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);

    if (savedInstanceState != null) 
    {
        Altodo = savedInstanceState.getStringArrayList("todo_arraylist");
        Log.v("bundle", "Restored");
    }
    else
    {
        Log.v("bundle", "null");
    }

    setContentView(R.layout.main);
}

The logs always show the "bundle save" tag.日志始终显示“捆绑保存”标签。

But in onCreate method, SavedInstanceState is always null.但在onCreate方法中, SavedInstanceState始终为 null。

I observed the exact same symptoms (reported as issue 133394 ) in a project with two Activities A and B that extend ActionBarActivity .我在一个项目中观察到完全相同的症状(报告为issue 133394 ),该项目有两个扩展ActionBarActivity的活动AB。 Activity A is the main activity, and I always receive null for savedInstanceState in onCreate of its list fragment when returning from a detail view activity B .活动A是主要活动,当从详细视图活动B返回时,我总是在其列表片段的onCreate中收到nullsavedInstanceState After many hours, this problem exposed itself to me as a navigation issue in disguise.几个小时后,这个问题作为一个变相的导航问题暴露给我。

The following may be relevant to my setup and come from other answers on this page:以下可能与我的设置相关,并且来自此页面上的其他答案:

  • Given this answer, I made sure that fragment and activity each have unique IDs set.鉴于这个答案,我确保片段和活动都设置了唯一的 ID。
  • There is no override of onSaveInstanceState without super call.没有super调用就不会覆盖onSaveInstanceState
  • Activity A is specified as acitivy B 's parent in AndroidManifest.xml , using both the android:parentActivityName attribute and the corresponding meta-data tag for earlier versions of Android (see " Providing Up Navigation "). Activity AAndroidManifest.xml中被指定为活动B的父级,同时使用android:parentActivityName属性和对应的meta-data标签,用于早期版本的 ZE84E30B9390CDB64DB6DB2C 导航“7468”。

Already without any corresponding creation code such as getActionBar() .setHomeButtonEnabled(true) , activity B has a functioning back button ( < ) in its action bar.在没有任何相应的创建代码(例如getActionBar() .setHomeButtonEnabled(true)的情况下,活动B在其操作栏中有一个正常工作的后退按钮 ( < )。 When this button is tapped, activity A reappears but with (a) all previous instance state lost, (b) onCreate always called, and (c) savedInstanceState always null .当点击此按钮时,活动A重新出现,但(a)所有先前的实例 state 丢失, (b)始终调用onCreate ,以及(c) savedInstanceState始终null

Interestingly, when I tap the back button provided at the bottom edge of the emulator display (an open triangle that points to the left), activity A reappears just as it was left (ie its instance state fully retained) without invoking onCreate .有趣的是,当我点击模拟器显示底部边缘提供的后退按钮(一个指向左侧的空心三角形)时,活动A会重新出现,就像它离开时一样(即它的实例 state 完全保留)而不调用onCreate So maybe something is wrong with navigation?那么导航可能有问题?

After more reading , I implemented my own navigation instructions to run in response to a tap on the back-button in activity B :经过更多阅读,我实现了自己的导航指令以响应在活动B中的后退按钮上的点击运行:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == android.R.id.home)
        NavUtils.navigateUpFromSameTask(this);
        return true;
    }
    return super.onOptionsItemSelected(item);
}

Nothing related to restoring instance state of activity A changed.与恢复活动A 的实例 state 相关的任何内容都没有更改。 NavUtils also provide a method getParentActivityIntent(Activity) and navigateUpTo(Activity, Intent) that allow us to modify the navigation intent to explicitly instruct that activity A is not started fresh (and thus without saved instance state provided) by setting the FLAG_ACTIVITY_CLEAR_TOP flag: NavUtils还提供了一个方法getParentActivityIntent(Activity)navigateUpTo(Activity, Intent)允许我们通过设置FLAG_ACTIVITY_CLEAR_TOP标志来修改导航意图以明确指示活动A不是重新开始(因此没有提供保存的实例 state):

If set, and the activity being launched is already running in the current task, then instead of launching a new instance of that activity, all of the other activities on top of it will be closed and this Intent will be delivered to the (now on top) old activity as a new Intent.如果设置,并且正在启动的活动已经在当前任务中运行,那么不会启动该活动的新实例,而是关闭它上面的所有其他活动,并且此 Intent 将被传递到(现在顶部)作为新意图的旧活动。

In my hands, this solves problem of lost instance state and could look like:在我手中,这解决了丢失实例 state 的问题,可能如下所示:

public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId()== android.R.id.home) {
        Intent intent = NavUtils.getParentActivityIntent(this);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        NavUtils.navigateUpTo(this, intent);
        return true;
    }
    return super.onOptionsItemSelected(item);
}

Note that this may not be the complete solution in other cases where a user can switch directly to activity B from within a different task (see here ).请注意,在用户可以从不同任务中直接切换到活动B的其他情况下,这可能不是完整的解决方案(请参阅此处)。 Also, a possibly identical solution in behavior that does not make use of NavUtils is to simply call finish() :此外,不使用NavUtils的行为可能相同的解决方案是简单地调用finish()

public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId()== android.R.id.home) {
        finish();
        return true;
    }
    return super.onOptionsItemSelected(item);
}

Both solutions work in my hands.两种解决方案都在我手中。 I am only speculating that the original issue is a slightly incorrect default implementation of the back-button, and it may be related to that implementation invoking some kind of navigateUp that misses FLAG_ACTIVITY_CLEAR_TOP .我只是推测最初的问题是后退按钮的默认实现稍微不正确,它可能与调用某种FLAG_ACTIVITY_CLEAR_TOPnavigateUp的实现有关。

Did you check if you have an Id set for that view ( if a view it is/has...).您是否检查过是否为该视图设置了 Id (如果视图是/具有...)。 onSaveInstanceState() is not called otherwise.否则不会调用 onSaveInstanceState()。

Check this link .检查此链接

The state saved in this manner is not persisted.以这种方式保存的 state 不会持久化。 If the whole application is killed as you are doing during debugging, the bundle will always be null in onCreate .如果整个应用程序在调试期间被终止,则捆绑包将始终是onCreate中的 null 。

This IMO is yet another example of awful Android documentation.这个 IMO 是糟糕的 Android 文档的又一个例子。 It's also why most apps in the marketplace don't implement saving state properly (at all).这也是为什么市场上的大多数应用程序都没有正确(完全)实现保存 state 的原因。

in Manifest add this line for activities在清单中为活动添加此行

android:launchMode="singleTop"

for example:例如:

<activity
        android:name=".ActivityUniversity"
        android:label="@string/university"
        android:launchMode="singleTop"
        android:parentActivityName="com.alkhorazmiy.dtm.ActivityChart">
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.alkhorazmiy.dtm.ActivityChart" />
    </activity>

How do you test it?你如何测试它?

Imo the best way to test it is using the "Don't keep activities"-flag in Settings > Developer Options. Imo 测试它的最佳方法是使用“设置”>“开发人员选项”中的“不保留活动”标志。 If you don't have Developer Options in Settings, see Enabling On-device Developer Options .如果您在设置中没有开发者选项,请参阅启用设备上的开发者选项

  1. Open your activity打开你的活动
  2. Long-press home长按首页
  3. Go to another application Go 到另一个应用程序
  4. Long-press home长按首页
  5. Go back to your application Go 返回您的应用程序

Shouldn't super.onSaveInstanceState(savedInstanceState);不应该super.onSaveInstanceState(savedInstanceState); be the first line in your override?成为您覆盖的第一行?

Edit : War_Hero points out in the comments that the documentation on that topic indicates that no, it shouldn't be the first line.编辑:War_Hero 在评论中指出, 关于该主题的文档表明不,它不应该是第一行。

Check your activity in AndroidManifest.xml and remove android:noHistory property if is true.检查您在AndroidManifest.xml中的活动,如果为真,则删除android:noHistory属性。

<activity
    // ....
    android:noHistory="false" />

I found that when I override onSaveInstanceState() and actually save some data in the Bundle , instance state is restored.我发现当我覆盖onSaveInstanceState()并实际在Bundle中保存一些数据时,实例 state 被恢复。 Otherwise it's not.否则不是。

Ive managed same way arround.我已经以同样的方式解决了问题。 Instead of handling savedInstanceState Bundle on the onCreateView method, ive handled it on onCreate method and setting the passed value to a globar variable then acessing this variable on the onCreateView method.我没有在 onCreateView 方法上处理 savedInstanceState Bundle,而是在 onCreate 方法上处理它并将传递的值设置为 globar 变量,然后在 onCreateView 方法上访问此变量。 Hope it helps.希望能帮助到你。

https://developer.android.com/guide/topics/manifest/activity-element#lmode https://developer.android.com/guide/topics/manifest/activity-element#lmode

From this you can see 'Similarly, if you navigate up to an activity on the current stack, the behavior is determined by the parent activity's launch mode.'从中您可以看到“同样,如果您向上导航到当前堆栈上的某个活动,则该行为由父活动的启动模式决定。” Maybe you are in the 'standard' mode.也许您处于“标准”模式。

I was able to solve it with:我能够通过以下方式解决它:

@Override public boolean onSupportNavigateUp()
{
    onBackPressed();
    return true;
}

still had parent set in the manifest.清单中仍然设置了父级。 So when you press the up navigation button, now it acts like the back button.因此,当您按下向上导航按钮时,它现在就像返回按钮一样。

To debug, consider implementing onRestoreInstanceState and placing a call to Log.d in this method.要进行调试,请考虑实现 onRestoreInstanceState 并在此方法中调用 Log.d。 Then, in the emulator, hit ctrl-F11 or whatever to rotate the phone.然后,在模拟器中,按 ctrl-F11 或其他任何方式来旋转手机。 Your call to Log.d should be hit.您对 Log.d 的调用应该会成功。

Implement a method of onRestoreInstanceState and put below code there实现一个onRestoreInstanceState方法并将下面的代码放在那里

Altodo = savedInstanceState.getStringArrayList("todo_arraylist");

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

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