屏幕旋转期间处理状态变化的最佳实践

3
我有一个非常简单的程序,其中包含一个Spinner和ToggleButton。当按钮被切换打开时,我禁用Spinner,并在切换关闭时启用它。我遇到了一个问题,这意味着在屏幕旋转期间Spinner被重新启用。我理解这是由于活动状态改变并且onCreate再次被调用,但我没有找到关于处理此类情况下视图状态的最佳实践的明确答案。
注意:我发现与此相关的最相关SO问题如下。所有3个问题都讨论如何处理状态更改(onPause / OnResume与覆盖onSaveInstanceState),但似乎没有澄清对于像这样简单的东西哪种是首选选项。

显然我对Android不是很熟悉,如果没有明确的选项,请告诉我。我只想把基础打好,不想养成坏习惯。 - KrustyGString
谢谢。这似乎是普遍共识。我是否正确地假设它在savedInstanceState中自动处理切换、spinnerSelections等,但由于启用不是一个“正常”的属性来检查,因此它不会被默认处理,这就是为什么必须手动完成的原因? - KrustyGString
哦,看起来另一个答案被删除了。如果您想在下面提供一个框架答案,我可以接受。再次感谢大家讨论。 - KrustyGString
查看此教程以了解如何使用保存的实例状态捆绑包来处理活动状态:http://www.quicktips.in/handling-activity-state-using-saved-instance-state-bundle/ - Deepak Swami
3个回答

5
Saving Android Activity state using Save Instance State的接受答案是正确的方法。
使用onSaveInstanceState保存一个布尔标志,指示下拉菜单是否被禁用,然后在onCreate(或onRestoreInstanceState)中读取该标志,并根据需要禁用下拉菜单。
如果您在XML布局中为视图设置了android:id并且不明确设置android:saveEnabled为false,则它们的“状态”将自动保存和恢复。例如,对于文本视图,包括当前在视图中的文本和光标位置。但似乎启用/禁用状态不是此“状态”的一部分。

完美的,谢谢。我的视图已经被赋予了android:id,但确认了我的猜想,即启用状态被排除在外。 - KrustyGString

0

系统如何自动保留ListView滚动位置?

您可能已经注意到,即使您没有处理onSaveInstanceState方法,某些数据在旋转期间也不会受到影响。例如:

  • EditText中的滚动位置文本
  • EditText中的文本等。

屏幕旋转时会发生什么?

当屏幕旋转时,系统会杀死活动的实例并重新创建一个新实例。系统这样做是为了为不同的配置提供最合适的资源给活动。当完整的活动进入多面板屏幕时,也会发生同样的事情。

系统如何重新创建新实例?

系统使用活动实例的旧状态来创建一个新实例,称为“实例状态”。实例状态是存储在Bundle对象中的键值对集合。

默认情况下,系统会将View对象保存在Bundle中,例如:滚动位置EditText等。

因此,如果您想保存应该在方向更改后继续存在的其他数据,则应覆盖onSaveInstanceState(Bundle saveInstanceState)方法。

在覆盖onSaveInstance方法时要小心!!!

@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
     // Save the user's current game state
     savedInstanceState.putInt(STATE_SCORE, mCurrentScore);

    // Always call the superclass so it can save the view hierarchy state
    super.onSaveInstanceState(savedInstanceState);
}

始终调用super.onSaveInstanceState(savedInstanceState),否则默认行为将无法正常工作。例如,在方向更改期间EditText的值将不会持久保存。不相信我吗?请查看此代码

恢复数据时使用哪种方法?

  • onCreate(Bundle savedInstanceState)

还是

  • onRestoreInstanceState(Bundle savedInstanceState)

这两种方法都获取相同的Bundle对象,因此在哪里编写恢复逻辑并不重要。唯一的区别是,在onCreate(Bundle savedInstanceState)方法中,您将需要进行空值检查,而在后一种情况下则不需要。

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mTextView = (TextView) findViewById(R.id.main);
        if (savedInstanceState != null) {
              CharSequence savedText = savedInstanceState.getCharSequence(KEY_TEXT_VALUE);
              mTextView.setText(savedText);
        }
}

OR

@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState);

    // Restore state members from saved instance
    mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
}

始终调用super.onRestoreInstanceState(savedInstanceState),以便系统默认恢复视图层次结构。

0
 <activity
        android:name="com.rax.photox.searchx.MainActivity"

        android:configChanges="keyboardHidden|orientation|screenSize"

它对我来说完美地运作了


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接