【奇技淫巧】使用 ProcessLifecycle 优雅地监听应用前后台切换
前言
很快乐见到你,又来到了「奇技淫巧」系列,本系列介绍一些「骚操作」,或许不适合用于生产,但可以开拓思路
前些天在群里看到有人评论通过维护 activity 栈来监听程序前后台0 * C @切换的问题。其实单纯监听程序的前后台切换完全不需求维护 activity 栈,而现在比较干流的做4 i H =法是运用 registerActivityLifecycl| 9 2 SeCallbacks
。而今天我来介绍一下运用 ProcessLifecycleOwner 来完结M a &这一功用
lifecycle-process 库
Android Jetpackm Q ` % 4 + Li& & y Z +fecycle 组件有一个可选库:lifecycle-process,它可认为整个 app 进程供给一个 P8 ) 9 processLifecyG v K | ~cleOwner

该库十分简单,只要四个文件

ProcessLifecycleOwnerInitializer
凭仗 ContentProvider 拿到 Context,用于初始化操作

EmptyActivityLifecycleCallbac_ ^ [ b l Sks
为 Application.ActivityLifecycleCallbacks
的完结类,内部为空完结

Lifecycle9 n & q 4 : # Dispatcher
通过 ReportFragment 来 hook 宿主的生命周期工作

中心逻辑都在 Pr2 9 S u # h W vocessLifecycleOwner 中

该类供给了整个 app 进程的 lifecycle
可以将其视为全部 activity 的 LifecycleOwner ,其中 Lifecycle.Event.ON_CREATE 只会分发一次,而 Lifecycle.Event.ON_DESTROY 则永远不会分发
其它的生命周X R 期工作将按以下规则分发:
ProcessLifecycleOwner
会分发 Lifecycle.Eve5 V I Ont.ON_START 和 Lifecycle.Event.ON_RESUb 8 z oME 工作(在第一个 activity 移动到这些工作时)
Lifecycle.Event.ON_PAUi & M ] T .SE 与 Lifecycle.Event.ON_STOP 会在最后一个 activity 移动到这些情况后 推延 分1 8 H # M a {发,O # 2 ^ .该推延满足长,以保证由于装备更改等操作重建 activity 后不会分发任何工作
对于监听运用在前后台切换且不需求毫秒级的精度的场景,这十分有用
ProcessLifecycleOwner 源码解析
依据上图我们得知 ProcessLifecycleOwn @ { 1 =ner
完结了 LifecycleOwner 接口
由于在 ProcessLifecycleOwnerInitializee o Xr
中初始化时传入了 Context,因而 ProcessLifecycleOwner
在 attach 方法中凭仗 Context 拿到了 Application 实例,并调用了 registerActivityLiJ P hfecycleCallbacks
void attach(Contey x 0 % y x I dxt context) {
mHandler = new Handler();
mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
Application app = (Application) context.getA4 u : upplicationContext();
app.registerActivityLifecycleCallbacks(new EmptyActivityLifecycleCallbacks()
@RequiresApi(29)
@Override
public void onAF / ] 1 o f y G }ctivityPreCreated(@NonNull Activity acti- ^ q T G ;vity,
@Nullable Bundle savedIT 5 5 p + ( + + enstanceState) {
//我们需求 ProcessLifecycleOwner 刚好在第一个 activity 的 Li[ r + 2 Y A 7 ifecycleOwnB n P B * W p qer started/resumed 之前获取 ON_START 和 ON_RESUME。
//ac0 : N w 4 q B b Ytivity 的 LifecycleOwner 通过在 onCreate() 中添加 activity 注册的 callback] V m L & = 0 i Y 来获取 started/resumed 情况。
//通过在 onActiv! ? _ k # !ityPreCreated() 中添加我们自己的 activity 注册的 callback,我们首要获得了回调,一同与 Activity 的 onStart()/ onResume()回调比较仍具有正确的相对次第
activity4 / G t N R u.registerActivityLifecycleCallbacks(new EmptyActivityLifecycl
@Override
public void onActivityPostStarted(@NonNull Activity activity) {
activit| u V K s n LyStarted();
}
@Override
public void onActivityPostResumed(@NonNull Activity activity) {
activityResumed();
}
});
}
@Override
public void onActivityCreated(Activity activity, Bund. M V } a $ Rle savedIn q 4 , / p T %stanceStat
//仅在API 29 之前运用 ReportFragment,在此之后,我们可以运用# R V g ! N %在 onActivityPreCreated() 中注册的 onActivityPostStarted 和 onActivityPostResumed 回调
if (BuilZ M Q N t Bd.VERSION.SDK_INT < 29) {
ReportFragment.get(activity).setProcessListener(mInitializationLi
}
}
@OY u l # 3 , ^ E @verrid[ ; P e De
public void onActivityPausn y ped(Activity activity) {
activityPaused();
}
@Override
public void onActivityStox r c J f ? 8 9 ,pped(Activity activity) {
activityStopped();
}
});
}
内部维护了 Started 和 Resumed 的数量
private int mStartedCounter = 0;
private int mResumedCounter = 0;
private boolean mPauseSent = true;
private boolean mStopSent = true;
并在 activityStarted 和 activityResumed 方法中对 这两个数值进行 ++,并更改 lC Z 8 ? { v u zifecycle 情况
void activityStarted() {
mStQ Z ;artedCounter++;
if (mStartedCounter == 1 && mStopSent) {
mRegistry.handleLifecyZ @ } , fcleEvent(Lifecycle.Event.ON_O = 9 k L ( ~START);
mStopSy ^ M [ yent = false;
}
}
void activityR( A ! +esumz W n h F $ Q Eed() {
mResumedCounter++;
if (mResumedCounter~ X h = == 1) {
if (mPauseSent) {
mRegistry.T W ) handleLifecycl` v y r 8 n x 3 WeEvent(Lifecycle.Eventy e { K , [.ON_RESUME);
m6 ] F ZPauseSent = false;
} else {
mHane 7 o Bdler.removeCallbacks(mDelayedPauseRunnable);
}
}
}
在 activityPaused 和 activityStopped 方法对这两个数值进行 —
void activityPaused() {
mResumedCounter--;
if (mResumedCg P i C / T { r &ounter == 0) {
mHandler.postDelayed(mDelayH b 4 ? Y 5 9edPauseRunnable, TIMEOUT_MS);
}
}
void activityStopped() {
mStartedCounter--;
dispatchStopIfNeeded();
}
而在这儿我们看到了上文说到的推延操作
// 运用 handler 进行推延操作
mHandU B T M :ler.postDelayed(mDela8 j O 0 iyedPauseRunnable, TIMEOUT_MS);
// 推延 700 ms
static final lS 7 ] $ @ong TIMEOUT_MS = 700; //mls
private Ruo E + ^nnable mDelayedPauseRunnable = new Runnable() {
@Override
public void run() {
// 依据需求分发工作
dispatchPauseIfNeede; e 9 ` e $d();
dispatchSt- = I )opIfNeeded();
}
};
void disp* s $ k (atchPauseIfNeeded() {
if (mResumedCounter == 0) {
mPauseSent = trueQ o Y x ] 4;
mRegistry.handleLifecI j ` . ;ycleEvent(Lifecycle.Event.{ J w B R S 3 / RON_PAU? L 1 BSEW u w } g ] H);
}
}
void dispatchStopIP x `fNeeded() {
if (mStartedCounter == 0 && mPauseSent) {
mRegistry.handleLifecycleEvent(Lifec4 G Dycle.Event.ON_STOP);
mStopSent = true;
}
}
源码就解析到这儿,接下来咱x I {们看看怎样运用吧
运用
首要引入该库
implementation "androidx.lifecycle:lifecycle-process:2.3.0-a _ B t ialpha05"7 4 3 P c R /
由于我们要自定义 lifec4 f T = , QycleObserver,因而还需引入
implementation "androidx.lifecycle:lifecyc8 M C U 3 % 0le-common-java8:2.Y * l a 3 $ : !3.0-alphI t s I u A T i (a05"
首要创立 ProcessLifecycleObserver
类,完结 DefaultLifecycleObserver
接口,在相应的生命周期中打印 log
接着在自定义 Ap= 2 x P .plicatiq Z i p b J i mon 中参加

这样便完结] ^ 6 { . w了!

Demo 在这儿
系列文章
-
【奇技淫巧】AndroidStudi~ C 8 uo Nea h j X dxus3n p I – N j.x 建立 Maven 私服遇到问题及处理计划
-
【奇技淫巧】什么?项目里 gradle 代码超越 200 行了!g m ) U ? 6 f你或许需求 Kotlin+buildSrc Plugin
-
【奇技淫巧】gradle 依托查找太麻烦?这个插件或许帮到你
-
【奇技淫巧】Android 组件化不运用 Router 怎样完结组件间 activity 跳转
-
【奇技淫巧】新的图片加载库?依据 Kotlin 协程的图片加载库——Cox G L G ^ E ? u *il
-
【奇技淫巧】运用 Navigation + Dynamic Feature Module 完结模– l + , E块化
-
【奇技淫巧】除了 bj x suildSrc 还能这样共同装备依托版本?巧用 includeBuild
-
【奇技淫巧】巧用 kotlin 扩展函数和 typealias 封装 带网络情况和处理「粘性」工作的 LiveData
关于我
我是 Flywith24,我Z b b的博客内容现已分类整理 在这儿,点击右上角的 Watch 可以及时获取0 _ 6 b z s C e我的文章更新哦
-
掘金
-
简书
-
Github
