一、StackTraceElement介绍:
StackTraceElement 保存的是 运行轨迹栈,就是你在执行的时候,运行过的线程、类和方法的记录,而这个得到的方法可以通过:
StackTraceElement[] trace = new Throwable().fillInStackTrace().getStackTrace();
我们可以看一下官方文档怎么说:
fillInStackTrace()方法保存的是当前线程的状态信息,然后再通过getStackTrace()方法获取出来,以StackTraceElement数组的形式保存起来。
我们再来看一下StackTraceElement有哪几个参数:
它可以保存四个参数:className、methodName、fileName和lineNumber.
我们在处理的时候根据需要具体处理就可以。
二、LogUtil的实现:
package com.fengjw.gridviewonlyonedemo;
import android.util.Log;
import java.util.Locale;
/**
* Created by fengjw on 2018/1/12.
*/
public class LogUtil {
private static boolean LOGV = true;
private static boolean LOGD = true;
private static boolean LOGI = true;
private static boolean LOGW = true;
private static boolean LOGE = true;
public static void v(String tag, String message){
if (LOGV){
Log.v(tag, message);
}
}
public static void d(String tag, String message){
if (LOGD){
Log.d(tag, message);
}
}
public static void i(String tag, String message){
if (LOGI){
Log.i(tag, message);
}
}
public static void w(String tag, String message){
if (LOGW){
Log.i(tag, message);
}
}
public static void e(String tag, String message){
if (LOGE){
Log.e(tag, message);
}
}
/**
* obtian caller class name
* @return class name
*/
private static String getTag(){
StackTraceElement[] trace = new Throwable().fillInStackTrace().getStackTrace();
String callingClass = "";
for (int i = 2; i < trace.length; i ++){
Class<?> clazz = trace[i].getClass();
if (!clazz.equals(LogUtil.class)){
callingClass = trace[i].getClassName();
callingClass = callingClass.substring(callingClass.lastIndexOf('.')+ 1);
break;
}
}
return callingClass;
}
/**
* direct output log message
*/
public static void v(String message){
if (LOGV)
Log.v(getTag(), message);
}
public static void d(String message){
if (LOGD)
Log.d(getTag(), message);
}
public static void i(String message){
if (LOGI)
Log.i(getTag(), message);
}
public static void w(String message){
if (LOGW)
Log.w(getTag(), message);
}
public static void e(String message){
if (LOGE)
Log.e(getTag(), message);
}
/**
* obtain Thread ID, Method Name, Output Message
* @param message
* @return String
*/
private static String buildMessage(String message){
StackTraceElement[] trace = new Throwable().fillInStackTrace().getStackTrace();
String caller = "";
for (int i = 2; i < trace.length; i ++){
Class<?> clazz = trace[i].getClass();
if (clazz.equals(LogUtil.class)){
caller = trace[i].getMethodName();
break;
}
}
return String.format(Locale.US, "[%d] %s : %s", Thread.currentThread().getId(),
caller, message);
}
/**
* direct output Thread ID, Method Name, Output Message
* Not define Tag
*/
public static void vThread(String message){
if (LOGV)
Log.v(getTag(), buildMessage(message));
}
public static void dThread(String message){
if (LOGD)
Log.d(getTag(), buildMessage(message));
}
public static void wThread(String message){
if (LOGW)
Log.w(getTag(), buildMessage(message));
}
public static void iThread(String message){
if (LOGI)
Log.i(getTag(), buildMessage(message));
}
public static void eThread(String message){
if (LOGE)
Log.e(getTag(), buildMessage(message));
}
}
【注】:i之所以从2开始,是因为前两个,也就是stack最上面的两个,必然是LogUtil的调用,所以就直接过滤调了。因为在调用LogUtil类的方法的时候,会调用两次方法,那么就会产生两个StackTraceElement对象,那么必然就会占用前两个,所以i是从2开始的。