应用前后台切换ProcessLifecycle的坑

183 篇文章 11 订阅

最近开发应用有这么一个需求,需要监听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前后台切换的接口。


————————————————
版权声明:本文为CSDN博主「水夸夸的梁郭先生」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Hunter_chemistry/article/details/123191580

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值