在性能调优时经常要打印函数执行时间、参数值等, 为了调试加了很多代码,调完后还要删掉, 这个事很繁琐。 我们可以用Android Profiler或methodtracing打印函数执行时间,但日志太多了且缺少参数值。所以JakeWharton写了个hugo库, 是用AspectJ实现的,基于AOP思想。 我看了hugo源码,总共四个文件左右,代码量很少。
我想做个同功能的插件,顺便学习一下gradle插件制作方法和字节码注入。
用法很简单,参考https://github.com/brycegao/TimePlugin/tree/master/demo
项目build.gradle文件里添加classpath和maven。
buildscript {
repositories {
google()
jcenter()
maven { url "https://dl.bintray.com/brycegmail/maven" }
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.3'
classpath 'com.brycegao.timeplugin:timeplugin:1.0.4'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
maven { url "https://dl.bintray.com/brycegmail/maven" }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
在app模块的build.gradle文件添加
apply plugin: 'timeplugin'
...
implementation 'com.brycegao.tpannotation:tpannotation:1.0.2'
在想打印日志的类或方法前添加注解@DebugLogger即可,用法参照hugo实现的。
@DebugLogger
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
showMsg(1, "this is test");
findViewById(R.id.btn_next).setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
startActivity(intent);
}
});
}
private void showMsg(int i, String msg) {
try {
Thread.sleep(100); //仅仅为了测试
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
}
}
运行程序:
原理:
注解的作用表示要修改哪个函数, gradle插件的作用是遍历.class, Javassist是字节码注入工具。
在编译期间进行字节码注入, 打开./app/build/intermediates/classes/debug/transforms/TPTransform/1目录可以看到修改后的字节码。
优点:在编译期间注入业务逻辑代码,比在源码里加log更方便,不用feature时只要配置gradle 插件不参与编译即可。
展望:在编译期间加日志只是一个点, 还可以实现很多其它业务逻辑。
完整代码:https://github.com/brycegao/TimePlugin 求star