从LeakCanary看Fragment生命周期监控

前文中我们已经了解到LeakCanary中Service生命销毁的监听方式,那么Fragment的生命周期监听又是怎么实现的呢?

Activity生命周期监听,在Application里面有ActivityLifecycleCallbacks,那么Fragment是否相似呢?我们的第一想法自然是查找系统中是否有FragmentLifecycleCallback之类的回调,在Android官方文档中查找FragmentLifecycleCallback,结果如下图:

可以看到在android.app,android.fragment.app以及android.support.v4.app包下均有FragmentLifecycleCallbacks类,那么该类的作用是否与我们期望一致,能否用于监听Fragment生命周期变化呢?我们来看下该类的说明以及相关接口:

Callback interface for listening to fragment state changes that happen within a given FragmentManager.

从该类说明可以看出其是用于监听给定FragmentManager中fragment状态变化的回调接口,也就意味着我们可以通过该接口来监听Fragment生命周期变化。

那么如何注册该接口作为Fragment生命周期监听器呢?其实前文截图中也有,registerFragmentLifecycleCallbacks,通过该方法我们就可以监听Fragment生命周期变化,该方法声明如下:

也就是说我们可以通过FragmentManager来注册FragmentLifecycleCallbacks作为监听器。

大家都知道FragmentManager需要通过Activity来获得,这也就意味着我们要获得Activity对象,问题进一步转化为全局监听Activity的生命周期变化,文章开头已经提到了,我们可以通过Application中的ActivityLifecycleCallbacks来监听Activity生命周期变化,那么Fragment生命周期监控的实现流程已经很清晰了:

  1. 监听Activity生命周期变化
  2. 在Activity创建时,获取其关联的FragmentManager对象
  3. 使用registerFragmentLifecycleCallbacks向FragmentManager注册监听器

监听Activity生命周期变化

监听Activity生命周期很简单,我们直接上代码:

less 复制代码
 application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {
     @Override
     public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
         // activity创建,获取其关联的FragmentManager
     }
 ​
     @Override
     public void onActivityStarted(@NonNull Activity activity) {
 ​
     }
 ​
     @Override
     public void onActivityResumed(@NonNull Activity activity) {
 ​
     }
 ​
     @Override
     public void onActivityPaused(@NonNull Activity activity) {
 ​
     }
 ​
     @Override
     public void onActivityStopped(@NonNull Activity activity) {
 ​
     }
 ​
     @Override
     public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {
 ​
     }
 ​
     @Override
     public void onActivityDestroyed(@NonNull Activity activity) {
 ​
     }
 });

获取关联的FragmentManager对象

从Activity中获取关联的FragmentManager对象时,需要注意的是,我们前文提到在android.app,android.fragment.app以及android.support.v4.app包下均存在FragmentManager,我们需要根据项目中是否使用到相关库来确定以那种方式获取FragmentManager对象。

判断项目中是否使用到相关库

对于Activity而言,我们并不能显示获取或指定Activity所使用的Fragment以及相关类,那么如何判断呢?简单来讲,我们是否可以认为,当代码中存在该包名下的文件时,则Activity有可能用到这个包名下的Fragment,此时我们就需要针对这类Fragment添加监听器。

怎么判断代码中是否存在该包名下的文件呢?通过类加载器,我们通过类加载器加载该包名下文件,如果成功加载,则说明项目中使用到了,如果加载异常,则说明项目中不存在,不需关注。类加载包含函数如下:

typescript 复制代码
 private boolean isClassAvailable(String classname) {
     try {
         Class.forName(classname);
         return true;
     }catch (Throwable e) {
         return false;
     }
 }

获取FragmentManager

scss 复制代码
 if ((isClassAvailable("androidx.fragment.app.Fragment") || isClassAvailable("android.support.v4.app.Fragment")) && activity instanceof FragmentActivity) {
     FragmentManager fragmentManager = ((FragmentActivity)activity).getSupportFragmentManager();
 }
 ​
 // Android O开始才有registerFragmentLifecycleCallbacks方法
 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
     android.app.FragmentManager fragmentManager = activity.getFragmentManager();
 }

注册监听器

注册监听器的代码实现比较简单,直接上代码:

typescript 复制代码
 fragmentManager.registerFragmentLifecycleCallbacks(new android.app.FragmentManager.FragmentLifecycleCallbacks() {
     @Override
     public void onFragmentDestroyed(android.app.FragmentManager fm, android.app.Fragment f) {
         super.onFragmentDestroyed(fm, f);
     }
 },true);

至此,我们就完成了Fragment生命周期的监听。

相关推荐
大白要努力!8 分钟前
Android opencv使用Core.hconcat 进行图像拼接
android·opencv
天空中的野鸟1 小时前
Android音频采集
android·音视频
小白也想学C2 小时前
Android 功耗分析(底层篇)
android·功耗
曙曙学编程2 小时前
初级数据结构——树
android·java·数据结构
闲暇部落4 小时前
‌Kotlin中的?.和!!主要区别
android·开发语言·kotlin
诸神黄昏EX6 小时前
Android 分区相关介绍
android
大白要努力!7 小时前
android 使用SQLiteOpenHelper 如何优化数据库的性能
android·数据库·oracle
Estar.Lee8 小时前
时间操作[取当前北京时间]免费API接口教程
android·网络·后端·网络协议·tcp/ip
Winston Wood8 小时前
Perfetto学习大全
android·性能优化·perfetto
Dnelic-11 小时前
【单元测试】【Android】JUnit 4 和 JUnit 5 的差异记录
android·junit·单元测试·android studio·自学笔记