前文中我们已经了解到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生命周期监控的实现流程已经很清晰了:
- 监听Activity生命周期变化
- 在Activity创建时,获取其关联的FragmentManager对象
- 使用registerFragmentLifecycleCallbacks向FragmentManager注册监听器
监听Activity生命周期变化
监听Activity生命周期很简单,我们直接上代码:
application.registerActivityLifecycleCallbacks(new Application.ActivityLifecycleCallbacks() {@Overridepublic void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {// activity创建,获取其关联的FragmentManager}@Overridepublic void onActivityStarted(@NonNull Activity activity) {}@Overridepublic void onActivityResumed(@NonNull Activity activity) {}@Overridepublic void onActivityPaused(@NonNull Activity activity) {}@Overridepublic void onActivityStopped(@NonNull Activity activity) {}@Overridepublic void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {}@Overridepublic 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添加监听器。
怎么判断代码中是否存在该包名下的文件呢?通过类加载器,我们通过类加载器加载该包名下文件,如果成功加载,则说明项目中使用到了,如果加载异常,则说明项目中不存在,不需关注。类加载包含函数如下:
private boolean isClassAvailable(String classname) {try {Class.forName(classname);return true;}catch (Throwable e) {return false;}
}
获取FragmentManager
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();
}
注册监听器
注册监听器的代码实现比较简单,直接上代码:
fragmentManager.registerFragmentLifecycleCallbacks(new android.app.FragmentManager.FragmentLifecycleCallbacks() {@Overridepublic void onFragmentDestroyed(android.app.FragmentManager fm, android.app.Fragment f) {super.onFragmentDestroyed(fm, f);}
},true);
至此,我们就完成了Fragment生命周期的监听。