JakeWharton的timber自动生成Tag原理
JakeWharton大神的timber是一个为懒人设计的、基于Android原生的Log扩展的Logger API。相对于原生的Log API,使用timber的好处是:
- 无须指明TAG,自动以当前Class Name为TAG
- 可以以String.format形式格式化输出日志内容
使用
从官网文档介绍,使用非常简单,分为2步:
- 在Application的oncreate进行初始化,如:
Timber.plant(new Timber.DebugTree()); - 日志记录,如:
Timber.d(“My Log”);
自动生成Tag原理
整个timber就一个Timber.java文件,也就500多行。通过阅读源码,我们可以发现生成Tag的代码:
@Override final String getTag() {
String tag = super.getTag();
if (tag != null) {
return tag;
}
StackTraceElement[] stackTrace = new Throwable().getStackTrace();
if (stackTrace.length <= CALL_STACK_INDEX) {
throw new IllegalStateException(
"Synthetic stacktrace didn't have enough elements: are you using proguard?");
}
return createStackElementTag(stackTrace[CALL_STACK_INDEX]);
}
其中核心就是这两句话:
StackTraceElement[] stackTrace = new Throwable().getStackTrace();
return createStackElementTag(stackTrace[CALL_STACK_INDEX]);
而其中CALL_STACK_INDEX是定义的常量5。
为什么CALL_STACK_INDEX是5呢?
我们还是从Timber.d()方法的调用堆栈入手,假设我们在DemoActivity里调用了Timber.d(“log”),调用时序如下:
从上面的时序图,我们可以知道new Throwable().getStackTrace()返回数组的前几个依次是:
- DebugTree
- Tree
- Tree
- TREE_OF_SOULS,也就是Timber$1
- Timber
DemoActiviy
因此,stackTrace[CALL_STACK_INDEX]也就是第6个DemoActivity就是我们所要获取的Tag
结论
timber自动生成Tag的技术要点就是:Throwable.getStackTrace()
这里的要强调一下Throwable.getStackTrace() 与
Thread.currentThread().getStackTrace()
是有所不同的,后者会多一些Thread.currentThread()的调用信息。