如果你想在你的Android程序中自动打印MainActivity.onCreate(line:37)这种类名.方法名(行数)的日志该如何实现呢?
1.引入Java的线程运行栈
Java.lang包中提供了StackTraceElement,可以用来获取方法的调用栈信息。通过调用线程函数Thread.currentThread().getStackTrace()可以获得StackTraceElement[]的堆栈数组,数组中保存了线程中的执行调用的方法。观察下面的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
StackTraceElement[] stacktrace = Thread.currentThread().getStackTrace();
System.out.println(
"call oncreate method"
);
System.out.println(
"stacktrace len:"
+ stacktrace.length);
for
(
int
i =
0
; i < stacktrace.length; i++) {
System.out.println(
"---- the "
+ i +
" element ----"
);
System.out.println(
"toString: "
+ stacktrace[i].toString());
System.out.println(
"ClassName: "
+ stacktrace[i].getClassName());
System.out.println(
"FileName: "
+ stacktrace[i].getFileName());
System.out.println(
"LineNumber: "
+ stacktrace[i].getLineNumber());
System.out.println(
"MethodName: "
+ stacktrace[i].getMethodName());
}
}
|

观察输出结果可以看出栈中先执行的方法是VM和Thread中的方法。第3条才是你调用所在的方法(调用getStackTrack的方法)。
2.日志模块设计
生成tag:
1
2
3
4
5
6
7
8
|
private
static
String generateTag(StackTraceElement stack){
String tag =
"%s.%s(L:%d)"
;
String className = stack.getClassName();
className = className.substring(className.lastIndexOf(
"."
)+
1
);
tag = String.format(tag, stack.getClassName(),className,stack.getLineNumber());
tag = customTagPrefix==
null
?tag:customTagPrefix+
":"
+tag;
return
tag;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public
static
void
d(String content){
if
(!allowD) {
return
;
}
StackTraceElement caller = Thread.currentThread().getStackTrace()[
3
];
String tag = generateTag(caller);
Log.d(tag, content);
}
public
static
void
d(String content,Throwable thr){
if
(!allowD) {
return
;
}
StackTraceElement caller = Thread.currentThread().getStackTrace()[
3
];
String tag = generateTag(caller);
Log.d(tag, content,thr);
}
|