[Android]应用前后台切换ProcessLifecycle的坑

最近开发应用有这么一个需求,需要监听app的生命周期,能够感知到用户划到后台,回到前台这些事件。

Google以及帮我们实现好了,只需在项目中引入依赖

 implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.0'
 implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'

然后自定义一个 LifecycleObserver,在这里面实现生命周期事件对应的响应逻辑。

object AppLifecycleObserver : LifecycleEventObserver {
    override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
        when (event) {
            Lifecycle.Event.ON_RESUME -> {}
            Lifecycle.Event.ON_STOP -> {}
        }
    }
}

在Application初始化时,注册这个LifecycleObserver

ProcessLifecycleOwner.get().lifecycle.addObserver(AppLifecycleObserver)

现在就可以轻松的监听App生命周期了。

按理说,软件逻辑应该是这样:当用户退到后台后,执行onStop方法。当用户切换回来时,执行onResume方法。

但是在测试的时候发现了这么一个问题,当退出应用又立马切回来的时候,并不会调用onStop和onResume方法。反反复复试了好几遍,就是存在这个问题,当切换的时间太短时,就监听不到了。这..这..这不对吧,我看今天是谁...谁要陷害我?

当我打开了ProcessLifecycleOwner的源码查看时,一个大大的TIMEOUT_MS映入眼帘。

 

好家伙,我就说怎么回事,原来还有个延时。

仔细研究一下源码。

ProcessLifecycleOwner通过ContentProvider来获取Application

 

然后通过对Application注册Activity的生命周期的回调来监听Activity的生命周期。

 

阅读源码后发现

在进行onPause 操作时,会进行延迟通知

并且通知时还会进行判断是否目前需要进行通知。

 

那么谷歌在这个地方这么做了一个延时是为什么呢?是为了防止用户误操作吗?

当我试图自己手写一个ProcessLifecycleOwner的时候,我才终于明白,原来这压根就是个技术问题。

我们的原理是监听Activity的生命周期,而当你在app内部新开一个Activity或者销毁Activity时,都会引起Activity调用onPause,onStop这些方法。所以,当ProcessLifecycleOwner接受到onPause,onStop这些事件时,并不知道是来自用户退到后台,还是来自app内部的Activity变化。

因此,这里才设置了一个延时,如果是app内部Activity变动,那么一个Activity的onPause必然会伴随另一个Activity的onResume。

这里说一下Activity启动和销毁时以及退到桌面时的生命周期事件:

在A中启动B:


A: onPause

B: onCreate

B: onStart

B: onResume

A: onStop

销毁B,回到A

B: onPause

A: onRestart

A: onStart

A: onResume

B: onStop

B: onDestroy

从app退到桌面:

onPause

onStop

由此可知,无论是哪种情况,onPause方法都会最先被调用,如果太长时间没有调用onResume,就认为是退到后台,如果很快onResume就被调用了,那就认为这只是app内部的activity在变化。这就是设置延时的作用。

终于破案了!原来安卓系统根本就没有提供app生命周期的接口,用监听Activity生命周期的方式来实现会有监听到onPause但是不知道是来自app内部Activity变化还是来自用户退到后台的问题。

解决方案

1、重写ProcessLifecycleOwner,将延时自己缩短点(谷歌官方定的是700毫秒),但也不能缩太短,否则可能新打开一个Activity都会被以为是滑到了后台。

2、自定义一个ProcessLifecycleOwner,在内部实现一个免除的信号量,当你在这个app内部要启动或者销毁Activity时,把这个信号量加一个。在ProcessLifecycleOwner中监听到onPause时,信号量为0则这个事件是来自系统的。信号量>0则这个事件是app内部的,这时不调用app的onPause方法,同时减去1,表示这次的免除机会已经被消费掉。

3、去求一下官方加一个app前后台切换的接口。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
如果需要监听整个 Android 应用后台切换,可以通过实现 `ActivityLifecycleCallbacks` 接口来实现,具体方法如下: 1. 在 `Application` 类中实现 `ActivityLifecycleCallbacks` 接口: ```java public class MyApplication extends Application implements ActivityLifecycleCallbacks { private int activityCount = 0; // 记录 Activity 的数量 @Override public void onCreate() { super.onCreate(); registerActivityLifecycleCallbacks(this); // 注册 Activity 生命周期回调接口 } @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { } @Override public void onActivityStarted(Activity activity) { activityCount++; if (activityCount == 1) { // 应用进入台 } } @Override public void onActivityResumed(Activity activity) { } @Override public void onActivityPaused(Activity activity) { } @Override public void onActivityStopped(Activity activity) { activityCount--; if (activityCount == 0) { // 应用进入后台 } } @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) { } @Override public void onActivityDestroyed(Activity activity) { } } ``` 2. 在 `onActivityStarted()` 和 `onActivityStopped()` 方法中统计应用中 `Activity` 的数量,当数量变为 0 时,说明应用进入了后台,当数量变为 1 时,说明应用进入了台。 这样,在整个应用进入后台时,系统会回调 `MyApplication` 中的 `onActivityStarted()` 和 `onActivityStopped()` 方法,从而实现监听整个应用后台切换

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水夸夸的梁郭先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值