Activity生命周期监听
使用 Instrumentation 对 Activity 生命周期进行监听。
优点:
- 全局仅一次反射,性能影响极小
- 所有Activity的生命周期都能够被监听到
- 由于Java的单继承,为了拓展性,可以使用装饰器模式对Instrumentation进行功能加强,但个人觉得这样做不推荐
缺点:
- 只使用于Activity的生命周期监听
- FragmentManger实例的应用关系复杂,不容易反射替代(应该可以实现,或者用其他方式Hook)
1. 实现原理:
回顾到 Activity 的启动流程,AMS 向 APP 进程发来 Activity 启动请求,ApplicaitonThread 作为binder线程的维护者收到消息,将消息回调到 ActivityThread 的Handler.handleMessage(),启动Activity。核心为:performLaunchActivity()->Instrumentation.callActivityOnCreate()->activity.performCreate()
类似的,还有:
//Instrumentation.java
pubilc void callActivityOnCreate(Activity activity,Bundle budle,PsersistableBundle p){
//...
}
public void callActivityOnCreate(Activity activity,Bundle
bundle){
//...
}
public void callActivityOnStart(Activity activity){
//...
}
//...OnPause、OnStop、OnDestroy也都类似
这些方法都是开放的,所有Activity的生命周期都会经过它,而且这些方法都明确了要调用哪个Activity的生命周期。这就给了我们一个机会来监听 Activity。同时这个设计也表现了 Android 的事件驱动设计。
2. 实现方法
我们可以通过继承一个 Instrumentation 来给这些方法加个钩子,注意一定要回调父类的本方法,否则就破坏程序了:
public class FyInstrumentation extends Instrumentation {
public static final String TAG = "FyInstrumentation";
//------------ onCreate ------------
@Override
public void callActivityOnCreate(Activity activity, Bundle bundle) {
Log.e(TAG, "begin onCreate: " + activity);
super.callActivityOnCreate(activity, bundle);
Log.e(TAG, "end onCreate" + activity);
}
@Override
public void callActivityOnCreate(Activity activity, Bundle bundle, PersistableBundle persistentState) {
Log.e(TAG, "begin onCreate: " + activity);
super.callActivityOnCreate(activity, bundle,persistentState);
Log.e(TAG, "end onCreate" + activity);
}
//-------------- onStart ---------------
@Override
public void callActivityOnStart(Activity activity){
Log.e(TAG, "begin onStart: " + activity);
super.callActivityOnStart(activity);
Log.e(TAG, "end onStart" + activity);
}
//-------------- onResume ---------------
@Override
public void callActivityOnResume(Activity activity){
Log.e(TAG, "begin onResume: " + activity);
super.callActivityOnResume(activity);
Log.e(TAG, "end onResume" + activity);
}
//-------------- onPause ---------------
@Override
public void callActivityOnPause(Activity activity){
Log.e(TAG, "begin onPause: " + activity);
super.callActivityOnPause(activity);
Log.e(TAG, "end onPause" + activity);
}
//-------------- onStop ---------------
@Override
public void callActivityOnStop(Activity activity){
Log.e(TAG, "begin onStop: " + activity);
super.callActivityOnStop(activity);
Log.e(TAG, "end onStop" + activity);
}
//-------------- onDestroy ---------------
@Override
public void callActivityOnDestroy(Activity activity){
Log.e(TAG, "begin onDestroy: " + activity);
super.callActivityOnResume(activity);
Log.e(TAG, "end onDestroy" + activity);
}
}
把我们的 FyInstrumentation 替换掉原有的 Instrumentation。
何时替换都可以,只需要在我们目标监听的 Activity 开始之前就替换好即可。所以我这里就把它放在 MyApplication 中,在所有 Activity 开始之前就替换好。
先写一个工具类,由于单例设计,ActivityThread实例的获取,我们可以通过静态方法currentActivityThread()
来获取。再对它的成员变量 mInstrumentation 进行反射替换成我们的 Instrumentation。
public class HookHelper {
public static final String TAG= "HookHelper";
public static void attachContext() throws Exception{
//获取到当前的activityThread
Class<?> atClazz = Class.forName("android.app.ActivityThread");
Method method = atClazz.getMethod("currentActivityThread");
Object at = method.invoke(null);
Log.e(TAG,at.getClass().getName()+" ");
Field f = at.getClass().getDeclaredField("mInstrumentation");
f.setAccessible(true);
f.set(at,new FyInstrumentation());
}
}
最后,我们在MyApplication中进行替换:
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
try {
HookHelper.attachContext();
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.测试监听:
进入到 MainActivity,然后点击按钮跳转到TestFragmentActivity:
2023-02-20 15:48:37.280 3737-3737/com.company.rxjavastudy E/FyInstrumentation: begin onCreate: com.company.lifecycle2.MainActivity@d3e13d
2023-02-20 15:48:37.700 3737-3737/com.company.rxjavastudy E/FyInstrumentation: end onCreatecom.company.lifecycle2.MainActivity@d3e13d
2023-02-20 15:48:37.703 3737-3737/com.company.rxjavastudy E/FyInstrumentation: begin onStart:
...
2023-02-20 15:52:39.380 3737-3737/com.company.rxjavastudy E/FyInstrumentation: end onStopcom.company.lifecycle2.MainActivity@d3e13d
内容太多了,我把顺序梳理如下:APP开启后进入到活动A,点击按钮跳转到活动B:
A-onCreate
A-onStart
A-onResume
A-onPause
B-onCreate
B-onStart
B-onResume
A-onStop
测试完成,监听成功。
对生命周期的细节,大家可以复习关于:Activity的四大启动模式与Activity跳转的生命周期的关系,也注意一下 onNewIntent(),这是在复用Activity的时候调用的。