在日常开发中 我们时常会需要打log或者debug来检查代码是否正确,来调试业务逻辑,但是 我们时常会因为修复bug而打很多log 但是事后又要一个一个去删除 不仅麻烦 而且耗时,所以有没有一种可以随时控制log是否输出和方法呢,当然有
接下来这篇文章就是从这个问题出发所做的关于如何随心打log 和如何快速定位log位置的文章
我们在查看崩溃日志的时候 经常会发现有类似于这样的日志
在我们的日志后面会有错误代码行数提醒 接下来
我们就要实现这样的功能 让我们的log不仅可以随时控制输出 而且知道我们输出的位置
好了
首先我们需要实现代码输出控制 ,我们在使用系统控制log输出的基础上封装一层
通过是否需要输出的布尔值来控制日志的输出 下面上代码:
private final static boolean DEBUG = true; public static void i(String tag,Object o) { if (DEBUG) { Log.i(TAG, tag+" "+String.valueOf(o)); } }类似于上面代码,我们自己新建一个类 专门用来打印我们自己的日志,在这个类中 我们可以通过 是否是debug模式 来控制是否打印log 我们只需要改变布尔值是true还是false就可以达到目的 ,好 现在日志的打印已经实现了随心控制 那么接下来 我们来实现如何在日志后面加上我们的代码位置行数
这里我们主要用到StackTraceElement这个类
先在这里放一下效果:
当我们打印这个log的时候 会在后面加上我们的代码位置 这样不仅便于找bug 同时 方便bug修复后删除日志
而实现这个 主要用到的类就是StackTraceElement,怎么用呢
客官请看:
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
通过当前线程拿到当前线程的栈帧集合,
这个可以理解为当我们调用方法的时候,每进入一个方法,会将该方法的相关信息(例如:类名,方法名,方法调用行数等)存储下来,压入到一个栈中,当方法返回的时候再将其出栈。
在这个集合里面我们有许许多多的信息 而我们需要的只是当前这个log类的信息 所有 我们要将信息筛选出来 那么怎么筛选呢
StackTraceElement给我们提供了四个主要的方法
分别为:
获取类名 ,获取文件名 获取方法名 获取所在行
那么问题就简单了
我们可以根据我们当前的这个log类名来筛选我们的信息
private static StackTraceElement getTargetStackTraceElement() { // find the target invoked method StackTraceElement targetStackTrace = null; boolean shouldTrace = false; StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); for (StackTraceElement stackTraceElement : stackTrace) { boolean isLogMethod = stackTraceElement.getClassName().equals(HBLog.class.getName()); if (shouldTrace && !isLogMethod) { targetStackTrace = stackTraceElement; break; } shouldTrace = isLogMethod; } return targetStackTrace; }HBlog是我的类的名字 大家要用直接改成自己当前的类的名字就可以了。
好 接下来只需要调用就可以了:
public static void i(String tag,Object o) { if (DEBUG) { StackTraceElement targetStackTraceElement = getTargetStackTraceElement(); Log.i(TAG, tag+" "+String.valueOf(o)+ "(" + targetStackTraceElement.getFileName() + ":" + targetStackTraceElement.getLineNumber() + ")"); } }就这样 只要在代码中调用这个方法 就会把相对应的文件名字 所在行数打印出来
贴下我的这个类的代码:
public class HBLog { private final static boolean DEBUG = true; private static final String TAG = "hb"; public static boolean isLogEnable(){ return DEBUG; } public static void i(String tag,Object o) { if (DEBUG) { StackTraceElement targetStackTraceElement = getTargetStackTraceElement(); Log.i(TAG, tag+" "+String.valueOf(o)+ "(" + targetStackTraceElement.getFileName() + ":" + targetStackTraceElement.getLineNumber() + ")"); } } public static void i(Object o) { if (DEBUG) { StackTraceElement targetStackTraceElement = getTargetStackTraceElement(); Log.i(TAG, String.valueOf(o)+"(" + targetStackTraceElement.getFileName() + ":" + targetStackTraceElement.getLineNumber() + ")"); } } private static StackTraceElement getTargetStackTraceElement() { // find the target invoked method StackTraceElement targetStackTrace = null; boolean shouldTrace = false; StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); for (StackTraceElement stackTraceElement : stackTrace) { boolean isLogMethod = stackTraceElement.getClassName().equals(HBLog.class.getName()); if (shouldTrace && !isLogMethod) { targetStackTrace = stackTraceElement; break; } shouldTrace = isLogMethod; } return targetStackTrace; } public static void d(String tag,Object o) { if (DEBUG) { StackTraceElement targetStackTraceElement = getTargetStackTraceElement(); Log.d(TAG, tag+" "+String.valueOf(o)+"(" + targetStackTraceElement.getFileName() + ":" + targetStackTraceElement.getLineNumber() + ")"); } } public static void d(Object o) { if (DEBUG) { StackTraceElement targetStackTraceElement = getTargetStackTraceElement(); Log.i(TAG, String.valueOf(o)+"(" + targetStackTraceElement.getFileName() + ":" + targetStackTraceElement.getLineNumber() + ")"); } } public static void e(String tag,Object o) { if (DEBUG) { StackTraceElement targetStackTraceElement = getTargetStackTraceElement(); Log.e(TAG, tag+" "+String.valueOf(o)+"(" + targetStackTraceElement.getFileName() + ":" + targetStackTraceElement.getLineNumber() + ")"); } } public static void e(Object o) { StackTraceElement targetStackTraceElement = getTargetStackTraceElement(); Log.e(TAG, String.valueOf(o)+"(" + targetStackTraceElement.getFileName() + ":" + targetStackTraceElement.getLineNumber() + ")"); } public static void e(Object o,Throwable t) { t.printStackTrace(); StackTraceElement targetStackTraceElement = getTargetStackTraceElement(); Log.e(TAG, String.valueOf(o) + " error:" + t.getMessage()+"(" + targetStackTraceElement.getFileName() + ":" + targetStackTraceElement.getLineNumber() + ")"); } public static void w(Object o) { if (DEBUG) { StackTraceElement targetStackTraceElement = getTargetStackTraceElement(); Log.w(TAG, String.valueOf(o)+"(" + targetStackTraceElement.getFileName() + ":" + targetStackTraceElement.getLineNumber() + ")"); } } public static void w(String tag,Object o) { if (DEBUG) { StackTraceElement targetStackTraceElement = getTargetStackTraceElement(); Log.w(TAG, tag+" "+String.valueOf(o)+"(" + targetStackTraceElement.getFileName() + ":" + targetStackTraceElement.getLineNumber() + ")"); } } // public static void w(Object o,Throwable t) { // if (DEBUG) { // t.printStackTrace(); // Log.w(TAG, String.valueOf(o) + " error:" + t.getMessage()); // } // } public static void v(Object o) { if (DEBUG) { StackTraceElement targetStackTraceElement = getTargetStackTraceElement(); Log.v(TAG, String.valueOf(o)+"(" + targetStackTraceElement.getFileName() + ":" + targetStackTraceElement.getLineNumber() + ")"); } } public static void v(String tag,Object o) { if (DEBUG) { StackTraceElement targetStackTraceElement = getTargetStackTraceElement(); Log.v(TAG, tag+" "+String.valueOf(o)+"(" + targetStackTraceElement.getFileName() + ":" + targetStackTraceElement.getLineNumber() + ")"); } } public static void d(Object... os) { if (DEBUG) { StringBuilder stringBuilder = new StringBuilder(); for (Object o: os) { stringBuilder.append(String.valueOf(o)).append(" "); } Log.d(TAG, stringBuilder.toString()); } } }
当然 log还有很多花样可以玩 不过这不是这篇文章的重点,样式如下 盗图一张:
网址如下:
里面各种各样的都有好了 就介绍到这里 希望各位大神不吝赐教。