Android 旋转屏幕时丢失数据
我的应用程序中有一个有趣的错误。当用户旋转屏幕时,我会丢失活动中的一些数据。有人知道为什么会这样吗 默认情况下,当屏幕旋转时,您的活动被终止并重新启动。为了确保没有数据丢失,您需要使用生命周期方法正确保存和恢复数据。看Android 旋转屏幕时丢失数据,android,android-activity,rotation,Android,Android Activity,Rotation,我的应用程序中有一个有趣的错误。当用户旋转屏幕时,我会丢失活动中的一些数据。有人知道为什么会这样吗 默认情况下,当屏幕旋转时,您的活动被终止并重新启动。为了确保没有数据丢失,您需要使用生命周期方法正确保存和恢复数据。看 这是系统在循环删除数据时保存数据的方式。我找到的最快解决方案是: 以下是@jaisonDavis有用答案的变体: int myInt; String myString; protected void onCreate(Bundle savedInstanceState) {
这是系统在循环删除数据时保存数据的方式。我找到的最快解决方案是:
以下是@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);
}
在本例中,变量在第一次创建活动时从
意图
初始化,但之后从savedInstanceState
初始化(如方向改变时)。这将解决保留状态的问题,但它只适用于片段
,而不是标准的活动
setRetainInstance(true);
在
onCreate()
方法中调用此函数 在AndroidManifest.xml中添加以下代码
<activity android:name=".MainActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
>
更多详细信息
人们已经提供了代码。所以我要补充更多的细节
当屏幕旋转时会发生什么?
当屏幕旋转时,活动的配置会发生变化,因此系统会为活动寻找更合适的资源。为此,系统将终止活动实例并重新创建新的活动实例
系统如何创建新实例?
系统尝试使用一组保存的旧活动实例数据(称为实例状态)重新创建实例。InstanceState是存储在束
对象中的键值对的集合
系统自动保存了一些数据
例如,默认情况下,系统将视图对象保存在捆绑包中
- 编辑文本中的文本
- 滚动列表视图中的位置等
EditText
中的文本将不保存。
如果你不相信我
使用哪种方法恢复状态?
包括我在内的许多人都感到困惑。我应该选择吗
onCreate(Bundle savedInstanceState)
onRestoreInstanceState(Bundle savedInstanceState)
onCreate(Bundle savedInstanceState)
方法中提供一个空检查。但是如果要在RestoreInstanceState(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)
,以便
系统默认情况下还原视图层次结构
Android引入了
ViewModel
,当屏幕旋转时,它可以存储复杂的对象。
ViewModel
类旨在以生命周期意识的方式存储和管理与UI相关的数据。ViewModel
类允许数据在配置更改(如屏幕旋转)后仍然有效
请参阅文件
在AndroidManifest.xml中添加以下代码
<activity android:name=".MainActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
>
它适用于我您可以使用MVVM模式并使用ViewModel保存数据。因此,当您旋转设备时,您不会担心丢失数据,因为您在ViewModel中隔离了数据,这意味着您的数据不会受到活动生命周期的影响。
配置更改解决了我的问题
<activity android:name=".MyActivity"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"
android:label="@string/app_name">
一个“ViewModel”是一个设计用于保存配置更改(如屏幕旋转)的类,可以保存视图所需的信息。当通过更改设备的配置或旋转来销毁“视图”(即片段/活动)时,其“ViewModel”不会被销毁,新的视图实例将重新连接到同一个“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
}
}
虽然有些数据是由Android-
EditText
contents保存的,例如。@RivieraKid我不知道你是否可以依赖它。你有没有看到任何地方的官员说这是事实?我会担心一些非品牌手机会稍微改变实现,如果它实际上不在规范中的话。最安全的做法是假设没有保存任何内容。@CherylSimon有freezesText
属性,默认情况下EditText
设置为true
。官方文件是。我从这里得到的。注意!super.onSaveInstanceState(savedInstanceState)应该在放置值之前调用。onRestoreInstanceState并不总是被调用。有趣的答案是:可以强制方向,使其无法旋转。如果持久性比允许旋转更重要,那么它是首选。在这种情况下,它保留了包括布局在内的所有内容。我希望布局应随方向而改变,但对象(如TextView)应继续显示旋转前显示的值。尽管这可能满足某些需要,但应避免使用此解决方案,除非它是最后的选择。在Android文档的开头甚至有一个警告。你从哪里得到这个方法的
public void onResume(){
super.onResume();
if (mViewModel.getSomeBooleanData()){
//...Do something when saved data is True
} else {
//...Do something when saved data is False
}
}