【发布时间】:2011-07-04 15:36:24
【问题描述】:
我的应用程序中有一个有趣的错误。当用户旋转屏幕时,我会丢失我活动中的一些数据。任何人都知道为什么会发生这种情况?
【问题讨论】:
-
一个有趣的答案:你可以强制一个方向,使它不能旋转。如果持久性比允许轮换更重要,那么它是首选。
标签: android android-activity rotation
我的应用程序中有一个有趣的错误。当用户旋转屏幕时,我会丢失我活动中的一些数据。任何人都知道为什么会发生这种情况?
【问题讨论】:
标签: android android-activity rotation
默认情况下,当屏幕旋转时,您的 Activity 会被终止并重新启动。为确保没有数据丢失,您需要使用生命周期方法正确保存和恢复数据。见Saving Persistent State。
【讨论】:
EditText内容。
EditText 的 freezesText 属性默认设置为 true。官方文档是developer.android.com/reference/android/widget/…。
//Use onSaveInstanceState(Bundle) and onRestoreInstanceState
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save UI state changes to the savedInstanceState.
// This bundle will be passed to onCreate if the process is
// killed and restarted.
savedInstanceState.putBoolean("MyBoolean", true);
savedInstanceState.putDouble("myDouble", 1.9);
savedInstanceState.putInt("MyInt", 1);
savedInstanceState.putString("MyString", "Welcome back to Android");
// etc.
super.onSaveInstanceState(savedInstanceState);
}
//onRestoreInstanceState
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// Restore UI state from the savedInstanceState.
// This bundle has also been passed to onCreate.
boolean myBoolean = savedInstanceState.getBoolean("MyBoolean");
double myDouble = savedInstanceState.getDouble("myDouble");
int myInt = savedInstanceState.getInt("MyInt");
String myString = savedInstanceState.getString("MyString");
}
当系统轮换删除数据时,这是您保存数据的方式。
【讨论】:
【讨论】:
这是@jaisonDavis 的有用答案的变体:
int myInt;
String myString;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_verses);
if (savedInstanceState == null) {
Intent intent = getIntent();
myInt = intent.getIntExtra("MyIntIntentKey", DEFAULT_INT);
myString = intent.getStringExtra("MyStringIntentKey", DEFAULT_STRING);
} else { // savedInstanceState has saved values
myInt = savedInstanceState.getInt("MyIntKey");
myString = savedInstanceState.getString("MyStringKey");
}
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putInt("MyIntKey", myInt);
savedInstanceState.putString("MyStringKey", myString);
super.onSaveInstanceState(savedInstanceState);
}
在此示例中,变量在第一次创建活动时从 Intent 初始化,但之后它们从 savedInstanceState 初始化(例如当方向改变时)。
【讨论】:
这将解决您保留状态的问题,但不幸的是,它仅适用于 Fragment 而不是标准的 Activity。
setRetainInstance(true);
在onCreate() 方法中调用它。
【讨论】:
在AndroidManifest.xml中添加如下代码
<activity android:name=".MainActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
>
【讨论】:
人们已经提供了代码。因此,我将添加更多详细信息。
当屏幕旋转时,Activity 的配置会发生变化,因此系统会为 Activity 寻找更合适的资源。为此,系统会终止该活动的实例并重新创建该活动的一个新实例。
系统尝试使用一组保存的旧 Activity 实例数据(称为实例状态)重新创建实例。 InstanceState 是 Key-Value 对的集合,存储在 Bundle 对象中。
默认情况下,系统会将 View 对象保存在 Bundle 中。
如果您想存储更多可以在方向更改后保留下来的数据。您应该覆盖 onSaveInstanceState(Bundle savedInstanceState) 方法。
@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中的文本将无法保存。 如果你不相信我check this out
包括我在内的许多人都感到困惑。我应该选择
onCreate(Bundle savedInstanceState)或
onRestoreInstanceState(Bundle savedInstanceState)没关系。两种方法都在参数中接收相同的包。唯一的区别是您需要在onCreate(Bundle savedInstanceState) 方法中提供一个空检查。但是如果你要使用onRestoreInstanceState(Bundle savedInstanceState),请谨慎使用
@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),这样 系统默认恢复View层级
【讨论】:
Android 引入了ViewModel,它可以在屏幕旋转时存储复杂对象。
ViewModel 类旨在以生命周期意识的方式存储和管理与 UI 相关的数据。 ViewModel 类允许数据在配置更改(例如屏幕旋转)后继续存在。
请参考文档
https://developer.android.com/topic/libraries/architecture/viewmodel
【讨论】:
在AndroidManifest.xml中添加如下代码
<activity android:name=".MainActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
>
对我有用
【讨论】:
您可以使用 MVVM 模式并使用您的 ViewModel 来保存数据。因此,当您旋转设备时,您不必担心丢失数据,因为您在 ViewModel 中隔离了数据,这意味着您的数据不会受到活动生命周期的影响。 https://developer.android.com/topic/libraries/architecture/viewmodel
【讨论】:
configChanges 解决了我的问题
<activity android:name=".MyActivity"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
android:label="@string/app_name">
【讨论】:
“ViewModel”是一个设计用于在配置更改(例如屏幕旋转)后保留的类,并且可以保留视图所需的信息。当“视图”(即片段/活动)通过更改设备的配置或旋转而被破坏时,其“视图模型”不会被破坏,并且视图的新实例将重新连接到相同的“视图模型”。
ViewModel 中的代码可能是这样的,以便 View 可以保存数据:
private boolean mSomeBooleanData = false;
public boolean getSomeBooleanData(){
return mSomeBooleanData;
}
public void setSomeBooleanData (boolean data) {
mSomeBooleanData = data;
}
现在在 Activity/Fragment 类的某处,从 ViewModel 调用这些方法,我们可以使用以下方法保存我们想要在旋转期间保存的数据:
mViewModel.setSomeBooleanData(true);
然后在 onResume() 方法中重新创建 Activity/Fragment 类时,我们可以从 ViewModel 中查找保存的数据并对其进行处理:
public void onResume(){
super.onResume();
if (mViewModel.getSomeBooleanData()){
//...Do something when saved data is True
} else {
//...Do something when saved data is False
}
}
【讨论】: