旋转屏幕时丢失数据
我的应用程序中有一个有趣的错误。当用户旋转屏幕时,我会丢失活动中的一些数据。任何人都知道为什么会发生这种情况?
I have a little funny bug in my application. When the user rotates the screen I lose some of the data in my activity. Anyone that have an idea of why this happens?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
这是当系统轮流删除数据时您保存数据的方式。
This is how you save your data when the system deletes it on rotation.
默认情况下,当屏幕旋转时,您的 Activity 将被终止并重新启动。为了确保不丢失数据,您需要使用生命周期方法正确保存和恢复数据。请参阅保存持久状态。
By default, when the screen is rotated your Activity is killed and restarted. To make sure no data is lost, you need to properly save and restore your data using the lifecycle methods. See Saving Persistent State.
更多细节
人们已经提供了代码。所以我将添加更多细节。
当屏幕旋转时会发生什么?
当屏幕旋转时,Activity 的配置会发生变化,因此系统会为 Activity 寻找更合适的资源。为此,系统会终止该活动的实例并重新创建该活动的新实例。
系统如何创建一个新的实例?
系统尝试使用一组旧 Activity 实例保存的数据(称为实例状态)重新创建实例。 InstanceState 是存储在
Bundle
对象中的键值对集合。系统自动保存一些数据
默认情况下,系统将 View 对象保存在 Bundle 中。
如果您想存储更多应在方向更改中幸存的数据。您应该重写
onSaveInstanceState(Bundle savingInstanceState)
方法。正确使用onSaveInstaneState
使用哪种方法来恢复状态?
很多人都感到困惑,包括我。我应该选择
onCreate(Bundle savingInstanceState)
还是
onRestoreInstanceState(Bundle savingInstanceState)
没关系。两种方法在参数中接收相同的包。唯一的区别是您需要在
onCreate(Bundle savingInstanceState)
方法中提供 null 检查。但如果您要使用onRestoreInstanceState(Bundle savingInstanceState)
,请谨慎使用More Detail
People have already provided the code. So I am going to add more details on that.
What happens when screen rotates?
When the screen rotates the configuration of the Activity changes so System looks for a more suitable resource for the Activity. For this purpose System kills the instance of the activity and recreates a new instance of the Activity.
How does System creates a new Instance?
System tries to recreate the instance using a set of saved data of old Activity instance known as instance state. InstanceState is a collection of Key-Value Pair stored in a
Bundle
object.System saved some data automatically
By default System saves the View objects in the Bundle for example.
If you want to store more data which should survive orientation change. You should override
onSaveInstanceState(Bundle savedInstanceState)
method.Use onSaveInstaneState correctly
Which method to use to restore state ?
Many people get confused including me. Should I choose
onCreate(Bundle savedInstanceState)
OR
onRestoreInstanceState(Bundle savedInstanceState)
It does not matter. Both methods receive the same bundle in the parameter. The only difference is that you need to provide a null check in
onCreate(Bundle savedInstanceState)
method. But if you are going to useonRestoreInstanceState(Bundle savedInstanceState)
, use it carefully以下是 @jaisonDavis 的有用答案的变体:
在此示例中,变量在第一次创建活动时从
Intent
初始化,但之后它们从savedInstanceState
初始化>(就像方向改变时一样)。Here is a variation on @jaisonDavis's helpful answer:
In this example the variables get initialized from an
Intent
on the first time the activity is created, but after that they get initialized fromsavedInstanceState
(like when the orientation changes).在 AndroidManifest.xml 中添加以下代码
In the AndroidManifest.xml add the following code
<activity android:name=".MainActivity"
android:configChanges="keyboardHidden|orientation|screenSize"
>
Android引入了
ViewModel
,它可以在屏幕旋转时存储复杂的对象。ViewModel
类旨在以生命周期意识的方式存储和管理 UI 相关数据。ViewModel
类允许数据在配置更改(例如屏幕旋转)中保留下来。请参阅文档
https://developer.android.com/topic/libraries/architecture/视图模型
Android has introduced
ViewModel
which can store Complex Objects when Screen is rotated.The
ViewModel
class is designed to store and manage UI-related data in a lifecycle conscious way. TheViewModel
class allows data to survive configuration changes such as screen rotations.Please refer to docs
https://developer.android.com/topic/libraries/architecture/viewmodel
在 AndroidManifest.xml 添加以下代码
它对我有用
In the AndroidManifest.xml add the following code
It works for me
这将解决您保留状态的问题,但不幸的是,它仅适用于
Fragment
而不适用于标准Activity
。在
onCreate()
方法中调用它。This will solve your issue of retaining state, but it only works for a
Fragment
and not a standardActivity
unfortunately.Call this in the
onCreate()
method.configChanges 解决了我的问题
configChanges solve my problem
您可以使用 MVVM 模式并使用 ViewModel 来保存数据。因此,当您旋转设备时,您不必担心丢失数据,因为您在 ViewModel 中隔离了数据,这意味着您的数据不会受到 Activity 生命周期的影响。
https://developer.android.com/topic/libraries/architecture/viewmodel
You can use MVVM pattern and use your ViewModel to save your data. So when you rotate your device you won't be worry about losing your data because you isolated your data in the ViewModel and that means your data won't be affected by activity lifecycle.
https://developer.android.com/topic/libraries/architecture/viewmodel
“ViewModel”是一个类,旨在适应配置更改(例如,屏幕旋转),并且可以保留视图所需的信息。当“View”(即片段/活动)通过更改设备的配置或旋转而被销毁时,其“ViewModel”将不会被销毁,并且新的View实例将重新连接到相同的“ViewModel”。
这就是 ViewModel 中的代码可能的样子,以便 View 可以保存数据:
现在在 Activity/Fragment 类中的某个位置,从 ViewModel 调用这些方法,我们可以保存 然后,当在 onResume () 方法中重新创建 Activity/Fragment类
时,我们可以从 ViewModel 中查找保存的数据并对其执行某些操作:
A “ViewModel” is a class designed to survive configuration changes (e.g., screen rotation) and can preserve the information necessary for the View. When “View” (i.e. fragment/activity) is destroyed by changing the configuration or rotation of the device, its “ViewModel” will not be destroyed and a new instance of View will be reconnected to the same “ViewModel”.
This is what the code in ViewModel might look like so that View can save the data:
Now somewhere in the Activity/Fragment class, calling these methods from the ViewModel we can save the data we want to save during rotation using:
Then when recreating the Activity/Fragment class in the onResume () method, we can look for that saved data from the ViewModel and do something with it: