Android方法耗时监控工具
1、背景
为了监控一些方法耗时
2、需求
要实现以下功能:
- Application onCreate()方法耗时
- Activity生命周期方法耗时
- Fragment生命周期方法耗时(TODO)
- 自定义方法耗时
- webview网页加载耗时
- …
3、实现
3.1、技术方案
利用Transform + ASM字节码修改技术动态插入代码
3.2、Application onCreate()方法耗时
考虑到App多重继承的情况,即App继承BaseApp,BaseApp继承Application;或者三方库需要代理App类,如Tinker。因此为了方便、统一处理,通过注解的方式,显示指定App类。
/**
* @description app类注解,用于指定启动的App类
* @Author pxq
* @Date 2020/8/7 17:44
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface App {
}
@App
public class MyApp extends BaseApp {
@Override
public void onCreate() {
//todo ...
}
}
3.3、Activity生命周期方法耗时
3.3.1、理论
1、Hook Instrumentation
优点:可以精确到各个生命周期
缺点:很多框架都Hook,比如插件化,需要重写大量方法兼容
2、Hook Handler或者Looper的Printer
优点:简单
缺点:只能无法精确到各个生命周期,只能计算onCreate 到 onResume的时间、存在Android版本兼容问题
参考:https://segmentfault.com/a/1190000020262028?utm_source=tag-newest
3.3.2、 Hook Instrumentation
Hook Instrumentation是比较完美的方案,这里使用这种方式。
/**
* @description 自定义代理Instrumentation,统计Activity生命周期耗时
* @Author panxq
* @Date 2020/8/7 17:59
*/
public class ProxyInstrumentation extends Instrumentation {
private Instrumentation baseIns;
// 控制一些变量,如打印阈值,是否重复打印等
private ActivityWire activityWire;
public ProxyInstrumentation(Instrumentation baseIns, ActivityWire activityWire) {
this.baseIns = baseIns;
this.activityWire = activityWire;
}
@Override
public void callActivityOnCreate(Activity activity, Bundle icicle) {
// 计算onCreate执行耗时
callOnPrev(activity, Trace.TRACE_ON_CREATE);
baseIns.callActivityOnCreate(activity, icicle);
callOnPost(activity, Trace.TRACE_ON_CREATE);
}
...下同
}
/**
* @description ActivityThread hook类
* @Author pxq
* @Date 2020/8/7 17:50
*/
public class ActivityThreadHooker {
private static final String TAG = "ActivityThreadHooker";
public static void hookIns(ActivityWire activityWire) throws Exception {
// 获取ActivityThread类
@SuppressLint("PrivateApi")
Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");<