后台模式下修改应用权限后Activity触发onCreate而非onResume,如何保留预实例化对象?
解决权限修改后Activity重建、对象丢失的问题
嘿,这个问题我之前帮不少开发者捋清楚过——其实这不是Activity生命周期的异常,而是Android系统的正常行为:当你修改应用的权限时,系统会认为应用的运行环境发生了重大变化,所以会销毁当前的Activity栈,再重新创建所有相关的Activity。这就是为什么你返回应用时触发的是onCreate(),而不是预期的onResume()。
不过别担心,我们有几种靠谱的方案可以帮你保留之前实例化的对象,下面逐一说明:
方案一:用onSaveInstanceState() + onRestoreInstanceState() 保存临时状态
这是Android官方推荐的保存Activity临时状态的方式,适合处理可序列化的数据:
- 先在Activity里重写
onSaveInstanceState(),把需要保留的对象(或者它的状态)存入Bundle:@Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); // 如果你的对象实现了Serializable接口,直接存入 outState.putSerializable("saved_object", myTargetObject); // 如果是基本数据类型,用对应的put方法,比如putString、putInt } - 然后在
onCreate()或者onRestoreInstanceState()里恢复数据:
小提示:如果你的对象不能直接序列化,可以让它实现@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); if (savedInstanceState != null) { // 从Bundle里取出之前保存的对象 myTargetObject = (MySerializableClass) savedInstanceState.getSerializable("saved_object"); } else { // 首次启动Activity时初始化对象 myTargetObject = new MySerializableClass(); } }Parcelable接口(比Serializable性能更高),或者把对象拆成基本数据类型分别保存。
方案二:用ViewModel 托管对象(最推荐)
ViewModel是Jetpack组件的一员,它的生命周期完全独立于Activity的重建——哪怕Activity被销毁重建,ViewModel里的数据也会保留,简直是为这种场景量身定做的:
- 先创建一个ViewModel类来持有你的对象:
public class MyDataViewModel extends ViewModel { private MyTargetObject myInstance; public MyTargetObject getMyInstance() { if (myInstance == null) { myInstance = new MyTargetObject(); } return myInstance; } } - 在你的Activity中获取ViewModel实例:
这种方式不需要手动处理序列化,代码简洁还不容易出错,非常推荐优先使用。@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 获取ViewModel,这里的this会让ViewModel和当前Activity绑定 MyDataViewModel viewModel = new ViewModelProvider(this).get(MyDataViewModel.class); // 这里拿到的就是之前实例化的对象,重建后也不会丢失 myTargetObject = viewModel.getMyInstance(); }
方案三:用单例模式(谨慎使用)
如果你的对象是全局唯一、且不依赖Activity生命周期的轻量对象,可以考虑用单例来保存:
public class MySingletonHolder { private static MySingletonHolder instance; private MyTargetObject myInstance; private MySingletonHolder() { // 初始化对象 myInstance = new MyTargetObject(); } // 获取单例实例 public static synchronized MySingletonHolder getInstance() { if (instance == null) { instance = new MySingletonHolder(); } return instance; } public MyTargetObject getMyInstance() { return myInstance; } }
之后在Activity里直接调用MySingletonHolder.getInstance().getMyInstance()就能拿到对象了。不过要注意:单例会一直驻留在内存中,直到应用进程被销毁,如果对象占用内存较大,可能会导致内存泄漏或占用过多资源,所以一定要谨慎使用。
总的来说,优先选ViewModel,它是最贴合Android生命周期设计的方案;简单状态用onSaveInstanceState()也足够;单例只适合特定场景下的轻量对象。
内容的提问来源于stack exchange,提问作者xelanac
相关产品推荐
相关产品推荐

