1.前言

开发过程中打日志已成为我们平时Debug调试不可缺少的一部分,Android SDK给我们也提供了很不错的工具类,并且分了不同的日志级别:Log.v() Log.d() Log.i() Log.w() and Log.e() 分别对应 VERBOSE,DEBUG,INFO, WARN, ERROR,其中Verbose不会在release版本中被编译进应用程序包中,而Debug日志根据Android API说会在运行时被去掉,另外的三个则会一直被保留。

2.问题

官方建议我们打日志的通用做法是:在你的类中声明一个常量TAG,如下

1
private static final String TAG = "MyActivity";

然后我们可以这样调用:

1
Log.v(TAG, "index=" + i);

细心的童鞋可能觉得官方给的有很多不足的地方,例如每个类都要声明TAG,日志不能追踪哪个类,哪个方法、哪一行,某些日志在App发布时不能自动删除,还需要手动修改或者删除等等。这里针对这些问题整理一些小技巧。

3.实践

  • 1.去掉TAG:我们可以用类名来作为TAG的内容,获取方法名和行数:

    1
    2
    3
    4
    5
    private static void getMethodNames(StackTraceElement[] sElements){
    className = sElements[1].getFileName();
    methodName = sElements[1].getMethodName();
    lineNumber = sElements[1].getLineNumber();
    }
  • 2.发布时去除日志
    Android的BuildConfig有一个很合适的DEBUG可以用,它在你发布release版本,这个bool值自动变为false;所以我们可以利用这一点,重新定义写Log的方法:

    1
    2
    3
    4
    5
    6
    7
    public static void v(String message){
    if (!BuildConfig.DEBUG)
    return;

    getMethodNames(new Throwable().getStackTrace());
    Log.v(className, createLog(message));
    }
  • 3.封装成方法

    1
    2
    3
    4
    5
    6
    7
    private static String createLog( String log ) {
    StringBuffer buffer = new StringBuffer();
    buffer.append(methodName);
    buffer.append("(").append(className).append(":").append(lineNumber).append(")");
    buffer.append(log);
    return buffer.toString();
    }

这样出来的结果就是:可以通过连接直接跳转到指定的文件的那一行

image
当然你也可以根据自己的喜好,修改要打印出来的格式。

  • 4.附上代码:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    public class LogUtils {
    static String className;//类名
    static String methodName;//方法名
    static int lineNumber;//行数

    private LogUtils(){
    /* Protect from instantiations */
    }

    public static boolean isDebuggable() {
    return BuildConfig.DEBUG;
    }

    private static String createLog( String log ) {
    StringBuffer buffer = new StringBuffer();
    buffer.append(methodName);
    buffer.append("(").append(className).append(":").append(lineNumber).append(")");
    buffer.append(log);
    return buffer.toString();
    }

    private static void getMethodNames(StackTraceElement[] sElements){
    className = sElements[1].getFileName();
    methodName = sElements[1].getMethodName();
    lineNumber = sElements[1].getLineNumber();
    }


    public static void e(String message){
    if (!isDebuggable())
    return;

    // Throwable instance must be created before any methods
    getMethodNames(new Throwable().getStackTrace());
    Log.e(className, createLog(message));
    }


    public static void i(String message){
    if (!isDebuggable())
    return;

    getMethodNames(new Throwable().getStackTrace());
    Log.i(className, createLog(message));
    }

    public static void d(String message){
    if (!isDebuggable())
    return;

    getMethodNames(new Throwable().getStackTrace());
    Log.d(className, createLog(message));
    }

    public static void v(String message){
    if (!isDebuggable())
    return;

    getMethodNames(new Throwable().getStackTrace());
    Log.v(className, createLog(message));
    }

    public static void w(String message){
    if (!isDebuggable())
    return;

    getMethodNames(new Throwable().getStackTrace());
    Log.w(className, createLog(message));
    }

    public static void wtf(String message){
    if (!isDebuggable())
    return;

    getMethodNames(new Throwable().getStackTrace());
    Log.wtf(className, createLog(message));
    }

    }
分享到:
移动开发者/技术爱好者/喜欢开源与分享,你也可以关注微信公众号MobDevGroup,移动开发在线分享:MobDevGroup