在Fragment、Activity及Application生命周期中保持数据的文摘整理及部分结论

本文档整理了在Android中如何在Fragment、Activity和Application的生命周期中保持数据,包括数据丢失场景、保存方法如savedInstanceState、static变量、singleton实例和持久化数据。特别指出,静态变量在app被销毁后会丢失,而savedInstanceState不能跨越app销毁恢复数据。建议根据应用需求选择合适的数据保持策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在Fragment、Activity及Application生命周期中保持数据的文摘整理及部分结论

问题梳理

     待保持的数据
          View状态
          属于fragments的数据
          属于Activity的数据
          属于app的数据,比如某个class里面的static数据

     在如下三种情况下存在数据保持问题
          在fragments之间切换
          在Activity之间切换
          在app之间切换

     数据保持被忽略的话,会出现很多奇怪的问题,比如空指针,比如突然发现数据不对了

     已知的保存方法
          系统自动保存view状态
          手工的savedInstanceState可以保存fragment或activity内部数据
          static variable、singleton instance
          preference或file或sqlite可以真正持久保持数据

     相关的问题
          怎样判断app是被销毁后重启的?
          在application生命周期内使用public static variable还是使用singleton实例来保存变量,并且具有唯一性?

Stackoverflow等的数据保持相关讨论

     可以使用全局静态变量吗?未必。

          如果app被遮盖,os不会单独销毁Activity,而是整个销毁process,如果os需要收回内存的话
               如果Activity被同app的其他Activity遮盖,这个Activity会被推入Activity栈

          So if you create an android application and initialize a static variable, it will remain in the JVM until one of the following happens:
          1. the class is unloaded
          2. the JVM shuts down
          3. the process dies
          可以在app内任意切换Activity。甚至可以切换到其他app,只要上述三者不发生。
          但切换到其他app后,os可能在需要内存时销毁本app的process及jvm,即2发生,于是static变量会被清空
          由此可见,通过static在app内交换数据是很好的选择,但app被销毁时数据会丢失

          那么,savedInstanceState是Activity被销毁时调用,但是能够跨越app被销毁?No,不能。
               部分相关文档


          系统帮忙恢复时,直接恢复最上层的Activity,而不是从main activity开始运行,所以可能很多静态变量没被初始化,还是null

          You should save your data somewhere more durable. 

          提及一个模拟低内存回收的方法
               运行app
               按home键
               通过android studio选择调试这个app,并且销毁这个app
               在手机上点击app的icon

          很多人建议extends Application来获得总会被初始化的全局变量,但必要性似乎有争议
               使用这种方法时注意修改AndroidManifest里面application标签里面的name
          

          Careful: the official documentation states, that you should save important information within the onPause-Method because 
          the onsaveinstance-method is not part of the android lifecycle. developer.android.com/reference/android/app/Activity.html 
          –  schlingel Jun 19 '12 at 7:40

          First, to clarify the 'intended' behavior: onSaveInstance and onRestoreInstance are fragile and only for transient state. 
          The intended usage (afaict) is to handle Activity recreation when the phone is rotated (orientation change). In other words, 
          the intended usage is when your Activity is still logically 'on top', but still must be reinstantiated by the system. The saved 
          Bundle is not persisted outside of the process/memory/gc, so you cannot really rely on this if your activity goes to the 
          background. Yes, perhaps your Activity's memory will survive its trip to the background and escape GC, but this is not 
          reliable (nor is it predictable). 
          这段话的关键点:这个savedInstanceState仅仅用于Activity始终在top却又需要被重建的场合。在进程之外并没有保存。
          理解:如果进程被杀,或者内存被回收,这个savedInstanceState就没有了
          但有个微质疑:Activity到了后台,但是app没到后台,这个saved bundle也不会丢吧?因为os总是整体性杀掉一个进程
               
          The onSaveInstanceState(bundle) and onRestoreInstanceState(bundle) methods are useful for data persistence merely 
          while rotating the screen (orientation change).
          They are not even good while switching between applications (since the onSaveInstanceState() method is called but 
          onCreate(bundle) and onRestoreInstanceState(bundle) is not invoked again.
          For more persistence use shared preferences. read this article:



          非常典型的情况
               使用一个独立的class的static变量来存放数据
               在extends Application里面初始化数据,数据源自文件

          问题是
               进程被销毁,static消失

          解决
               preference



          怎样声明全局变量?
               推荐extends application


          文中引用android官方说法,即使用public static fields and/or methods
          这的确是最简单直接的方法
          不过答案是2010年的,相关链接已经失效


          介绍了从静态变量到singleton的心路历程。。。。但是其理解似乎并不正确

          文中提及,假定一个static variable被一个activity初始化,但如果activity消失,这个变量可能变成未初始化
          我的理解是,这通常是不可能的,但按如下次序重建app则可能:
               app a启动
               activity1启动,并且初始化独立类里面的静态变量 var
               切换到activity2
               切换到其他app b,导致app a被销毁
               切换回app a,导致app a重建
               app a的重建过程是:
                    给var分配空间,但值为null
                    重建activity2
                    开始运行
               注意,这种情况下不会重建activity1,故没有对var的初始化,这导致该var为null
               
          文章下面有很多回复
               Igor Ganapolsky的解释似乎与我的认识一致,即博主所言静态变量被修改是因为app重建的缘故,也只能是这个缘故
               有了extends application就不用singleton,因为前者就是很好的singleton
               Larry的解释非常完备,可以作为本论题的总结。内容与我前面提及的“按如下次序重建app”近似。
                    I struggled with this problem as well and after a lot of research I have come to the following conclusions. 
                    The Android OS will NOT discard static data, singletons, etc. The only action Android will do is discard Activities, 
                    【os不会删除static data,singleton等,只会销毁或重建activity】
                    since activities can be recreated easily. It doesn’t make sense that random static variables or classes will be discarded.
                    When your application is in the background, and the OS needs memory, it will shut down activities and recreate them 
                    【如果app在后台运行,并且如果os需要内存,则会销毁activity,在app回到前台时重建activity】
                    when you bring the app to the foreground again. If memory is low, it may kill your application all together (reclaims all 
                    the memory including the application class). At this point, all your static data is gone as well (obviously).
                    【如果app在后台运行,并且内存非常紧张,os可能销毁整个app,当然包括static data自然也被销毁了】
                    If within about 30 minutes of this occurring, you select your app again, the OS will attempt to put it back where it was 
                    when it was killed. It will recreate the application (and hence run the OnCreate() in the application Class) and then restart 
                    the Activity which was visible when you put the app in the background earlier. It does not recreate the activity stack – only 
                    【app返回前台时,除了重建application数据之外,会重建销毁时最顶层的那一个activity,而不会重建整个activity栈】
                    the last activity that was visible. So, if you initialize your singleton Class in the Application class, it should work fine. But if 
                    【如果在application里面初始化singleton数据,这没问题】
                    your initialize data in your singleton Class in say the first activity that starts the app (Main_activity for example), then that 
                    【如果在main activity里面初始化singleton数据,而这个main activity不在最顶层而未被恢复,那么这个singleton将没有机会被初始化】
                    static data will NOT be there.
                    You will need to check in each activity onCreate() if the singleton is there and initialized. If not, you should restart your app 
                    by starting the Main_Activity again.


部分结论
     如果app始终在屏幕上,进程不会被销毁,可以使用savedInstanceState、static变量来保持数据,view内部状态系统会自行保持
     如果app被隐藏,则存在进程被销毁的可能,就应该持久化数据,比如preference

     


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值