利用线程运行栈StackTraceElement设计Android日志模块

来源:互联网 发布:阿里云系统怎么样os 编辑:程序博客网 时间:2024/06/01 08:17

如果你想在你的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
  protectedvoid 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(inti = 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());
      }
  }
在onCreate方法中调用getStackTrace方法获取调用栈的信息。打印的结果如下: \
观察输出结果可以看出栈中先执行的方法是VM和Thread中的方法。第3条才是你调用所在的方法(调用getStackTrack的方法)。 

2.日志模块设计

生成tag:
?
1
2
3
4
5
6
7
8
privatestatic 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;
        returntag;
    }
CustomTagPrefix是自定义的前缀。 包装LOG:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
publicstatic void d(String content){
        if(!allowD) {
            return;
        }
        StackTraceElement caller = Thread.currentThread().getStackTrace()[3];
        String tag = generateTag(caller);
        Log.d(tag, content);
    }
     
    publicstatic void d(String content,Throwable thr){
        if(!allowD) {
            return;
        }
        StackTraceElement caller = Thread.currentThread().getStackTrace()[3];
        String tag = generateTag(caller);
        Log.d(tag, content,thr);
    }
getStackTrace()[3],取第四个的原因是前两个分别为vm和Thread的方法,下标2是当前的d()方法,调用d()的方法的下标为3。 

0 0