android APP从后台重启后如何避免异常

Android应用后台运行与数据保存策略
本文讨论了Android应用在后台运行时如何保存数据,包括Home键、长按Home键、电源键、启动新Activity、屏幕方向切换等情况,重点介绍了Activity的onSaveInstanceState()和onRestoreInstanceState()方法的作用及使用场景,以及如何通过BaseActivity实现统一的数据保存,确保应用重启后数据不丢失。


android中,当我们按home键(一般指手机的物理按钮的中间那个键)回到手机桌面,此时app并没有退出,而是一直运行与后台中,此时如果我们点击app图标,还是会进入刚刚的界面之中。但是这存在一个问题,就是如果内存紧张或者当我们回到桌面,点击了别的应用造成内存紧张,此时再通过点击图标进入app,此时会出现异常。这样造成的用户感觉非常不好!
其实,归纳起来,并不仅仅这种情况下造成数据丢失,造成数据丢失的情况有如下几种:
(1)、当用户按下HOME键时。
  这是显而易见的,系统不知道你按下HOME后要运行多少其他的程序,自然也不知道activity A是否会被销毁,因此系统会调用onSaveInstanceState(),让用户有机会保存某些非永久性的数据。
  (2)、长按HOME键,选择运行其他的程序时。
  (3)、按下电源按键(关闭屏幕显示)时。
  (4)、从activity A中启动一个新的activity时。(这种情况应该是,当我们在activity A时,此时通知栏有其他的通知,我们点击通知启动activity B,此时我们进入别的应用)
  (5)、屏幕方向切换时,例如从竖屏切换到横屏时。
值得幸运的是,android对此提供了非常好的解决办法!
Activity的 onSaveInstanceState() 和 onRestoreInstanceState()并不是生命周期方法,它们不同于 onCreate()、onPause()等生命周期方法,它们并不一定会被触发。当应用遇到意外情况(如:内存不足、用户直接按Home键)由系统销毁一个Activity时,onSaveInstanceState() 会被调用。但是当用户主动去销毁一个Activity时,例如在应用中按返回键,onSaveInstanceState()就不会被调用。因为在这种情况下,用户的行为决定了不需要保存Activity的状态。通常onSaveInstanceState()只适合用于保存一些临时性的状态,而onPause()适合用于数据的持久化保存。
  在activity被杀掉之前调用保存每个实例的状态,以保证该状态可以在onCreate(Bundle)或者onRestoreInstanceState(Bundle) (传入的Bundle参数是由onSaveInstanceState封装好的)中恢复。这个方法在一个activity被杀死前调用,当该activity在将来某个时刻回来时可以恢复其先前状态。
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    if (savedInstanceState != null) {
        mIndividual = (Individual) savedInstanceState.get("mIndividual");
    }
}

@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
    outState.putSerializable("mIndividual", mIndividual);
    super.onSaveInstanceState(outState, outPersistentState);
}

?实例代码如上,通过重写上面两个方法保存一些需要当前界面或者整个应用需要使用的数据,缓存起来,等到重新启动时,这些数据依然存在,这样重启之后不会造成app异常退出!
需要提醒的是,我们开发一个app的时候,activity是非常多的,一个界面中需要的数据很多,并且不知道用户会在哪个activity中按下Home键退回到了手机桌面,这样该如何处理呢?
此时的解决办法是,使用一个基本BaseActivity,在BaseActivity重写onSaveInstanceState和onRestoreInstanceState两个方法,然后每个界面Activity继承基类BaseActivity,这样不必每个activity重写这两个方法,同时,不管在哪个activity中按下home键,都会把数据保存起来,重启之后数据不至于丢失!
另外,还有一个地方需要说明,有些app可能想每次点击应用图标的时候,都能够进入主界面,不管此时app处于什么状态,不管app此时是否运行与后台,这时可以使用activity的配置 <category android:name="android.intent.category.LAUNCHER">?启动的activity中配置android:launchMode=”singleTask”即可。这样配置,保证每次点击应用图标,都进入主界面内,不管此时app是否运行与后台之中。

### 实现Android应用在后台持续运行 对于保持Android应用程序在后台持续运行,自Android Oreo (API level 26)以来引入了新的限制措施来优化电池寿命和系统资源管理。为了适应这些变化并确保服务能够稳定工作于后台环境之中,开发者可以采用如下几种策略[^1]。 #### 使用JobScheduler替代传统Service 当目标是在设备处于空闲状态或充电状态下执行某些操作时,`JobScheduler`是一个很好的选择。它允许任务被安排在一个更加灵活的时间框架内被执行,并且可以根据网络条件等因素自动调整执行时机。这不仅有助于节省电量消耗,同时也提高了用户体验的质量。 ```java ComponentName componentName = new ComponentName(context, MyJobService.class); JobInfo jobInfo = new JobInfo.Builder(0, componentName) .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY) .build(); JobScheduler scheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE); scheduler.schedule(jobInfo); ``` #### 利用WorkManager处理长期异步任务 如果需要保证即使手机重启之后也能继续完成的任务,则应该考虑使用`WorkManager`库。该组件专为持久化作业设计,能够在满足特定约束条件下可靠地调度一次性或多周期性的任务。 ```kotlin val myWorkRequest = OneTimeWorkRequestBuilder<MyWorker>() .setConstraints( Constraints.Builder() .setRequiresCharging(true) .build()) .build() WorkManager.getInstance().enqueue(myWorkRequest) ``` #### 前台服务(Foreground Service) 创建一个前台服务是一种让重要进程维持活跃的有效方式。通过显示通知给用户表明有正在进行中的活动,这样既可以让程序长时间占用CPU时间而不受操作系统的影响,又能让用户清楚知道当前有什么正在发生的事情。 ```java Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID) .setContentTitle("Foreground Service") .setContentText("Running...") .build(); startForeground(NOTIFICATION_ID, notification); // Remember to stop the foreground service when it's no longer needed. stopForeground(true); // Remove the notification and release resources. ``` 以上方法均适用于不同场景下的需求,具体选用哪种取决于实际应用场景以及所期望达到的效果。值得注意的是,在开发过程中应当遵循最佳实践指南以减少不必要的性能开销并对用户的隐私给予充分尊重。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值