当前位置: 首页 > news >正文

高效获知Activity的生命周期

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   ------------@Overridepublic void callActivityOnCreate(Activity activity, Bundle bundle) {Log.e(TAG, "begin onCreate: " + activity);super.callActivityOnCreate(activity, bundle);Log.e(TAG, "end onCreate" + activity);}@Overridepublic 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 ---------------@Overridepublic void callActivityOnStart(Activity activity){Log.e(TAG, "begin onStart: " + activity);super.callActivityOnStart(activity);Log.e(TAG, "end onStart" + activity);}//--------------  onResume ---------------@Overridepublic void callActivityOnResume(Activity activity){Log.e(TAG, "begin onResume: " + activity);super.callActivityOnResume(activity);Log.e(TAG, "end onResume" + activity);}//--------------  onPause ---------------@Overridepublic void callActivityOnPause(Activity activity){Log.e(TAG, "begin onPause: " + activity);super.callActivityOnPause(activity);Log.e(TAG, "end onPause" + activity);}//--------------  onStop ---------------@Overridepublic void callActivityOnStop(Activity activity){Log.e(TAG, "begin onStop: " + activity);super.callActivityOnStop(activity);Log.e(TAG, "end onStop" + activity);}//--------------  onDestroy ---------------@Overridepublic 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{//获取到当前的activityThreadClass<?> 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 {@Overridepublic 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的时候调用的。

http://www.lryc.cn/news/14303.html

相关文章:

  • 分析现货黄金价格一般有什么方法
  • Spring中的拦截器
  • 【Linux操作系统】【综合实验四 Linux的编译环境及线程编程】
  • Switch 如何使用NSCB 转换XCI NSP NSZ教程
  • JVM12 字节码指令集
  • centos之python安装与多版本python之间的共存
  • SpringBoot学习笔记(一)
  • 美国原装KEYSIGHT E4981A(安捷伦) E4981A电容计
  • K8S的基础概念
  • 【数据结构】——环形队列
  • windows 安装Qt
  • spring cloud gateway集成sentinel并扩展支持restful api进行url粒度的流量治理
  • wafw00f工具
  • 论文阅读笔记-DiffusionInst: Diffusion Model for Instance Segmentation
  • 解决CondaUpgradeError网上的方法都不奏效(回退版本、upgrade/update都不行)的问题和CondaValueError
  • 基于某业务单登陆场景并发测试实战
  • JVM内存模型
  • 三、NetworkX工具包实战3——特征工程【CS224W】(Datawhale组队学习)
  • 分布式之Raft共识算法分析
  • 数据库——范式
  • Geospatial Data Science(2):Geospatial Data in Python
  • 16.hadoop系列之MapReduce之MapTask与ReduceTask及Shuffle工作机制
  • java 面试过程中遇到的几个问题记录20230220
  • 面试题:【数据库三】索引简述
  • 数据库必知必会:TiDB(12)TiDB连接管理
  • 电源大事,阻抗二字
  • ASE20N60-ASEMI的MOS管ASE20N60
  • nginx 代理01(持续更新)
  • 初阶C语言——操作符【详解】
  • 37k*16 薪,年后直接上岗,3年自动化测试历经3轮面试成功拿下阿里Offer....