解决方案

2.1 消灭TAG

我们用TAG就是做定位,同时方便过滤无意义的log。那么索性把当前类名作为这样一个TAG的标识。于是,在我们自定义的log类中就用如下代码设置tag:

  1. /**
  2. * @return 当前的类名(simpleName)
  3. */
  4. private static String getClassName() {
  5. String result;
  6. StackTraceElement thisMethodStack = (new Exception()).getStackTrace()[2];
  7. result = thisMethodStack.getClassName();
  8. int lastIndex = result.lastIndexOf(".");
  9. result = result.substring(lastIndex + 1, result.length());
  10. return result;
  11. }

这样我们就轻易的摆脱了tag的纠缠。

这个方法来自于豪哥的建议,这里感谢豪哥的意见。

2.2 将Log简化

有人说我们IDE不都有代码提示了么,为啥还用一个L来做简化。首先用L比log能更快的得到提示,输入一个l.d就会直接显示提示,并且不会和原本的log类混淆。其次就是调用更方便。简化log这个东西太简单了,直接自定义一个L类,用作Log的输出即可。

2.3 在终端能显示当前类名并且增加超链

这个功能其实ide是支持的,只不过我们可以通过一些神奇的方法来做到更好的效果。下面就给出两个可行的方法:

  1. /**
  2. * @return 当前的类名(全名)
  3. */
  4. private static String getClassName() {
  5. String result;
  6. StackTraceElement thisMethodStack = (new Exception()).getStackTrace()[1];
  7. result = thisMethodStack.getClassName();
  8. return result;
  9. }
  10. /**
  11. * log这个方法就可以显示超链
  12. */
  13. private static String callMethodAndLine() {
  14. String result = "at ";
  15. StackTraceElement thisMethodStack = (new Exception()).getStackTrace()[1];
  16. result += thisMethodStack.getClassName()+ ".";
  17. result += thisMethodStack.getMethodName();
  18. result += "(" + thisMethodStack.getFileName();
  19. result += ":" + thisMethodStack.getLineNumber() + ") ";
  20. return result;
  21. }

2.4 让log更加美观

人们对美的追求真是无止境,更加美丽的log也能方便我们一下子区分什么是系统打印的,什么是我们自己应用打印的。做到这点也比较简单,就是在输出前做点字符串拼接的工作。

  1. private static final char TOP_LEFT_CORNER = '╔';
  2. private static final char BOTTOM_LEFT_CORNER = '╚';
  3. private static final char MIDDLE_CORNER = '╟';
  4. private static final char HORIZONTAL_DOUBLE_LINE = '║';
  5. private static final String DOUBLE_DIVIDER = "════════════════════════════════════════════";
  6. private static final String SINGLE_DIVIDER = "────────────────────────────────────────────";
  7. private static final String TOP_BORDER = "╔════════════════════════════════════════════════════════════════════════════════════════";
  8. private static final String BOTTOM_BORDER = "╚════════════════════════════════════════════════════════════════════════════════════════";
  9. private static final String MIDDLE_BORDER = "╟────────────────────────────────────────────────────────────────────────────────────────";
  10. private static String TAG = "PRETTYLOGGER";

因为打印log也是消耗性能的,所以我建议最多只保留出现某些异常(这些异常轻于Exception)时打印的log,在调试时打印的log在提交代码前请全部清除。

2.5 让log支持输出object、map、list、array、jsonStr等对象

这个需求实现起来也比较容易,如果是简单的POJO的对象,我们用反射得到对象的类变量,通过字符串拼接的方式最终输出值。如果是map等数组结构,那么就用其内部的遍历依次输出值和内容。如果是json的字符串,就需要判断json的{},[]这样的特殊字符进行换行处理。

2.6 增加log自动化和强制开关

区分release和debug版本有系统自带的BuildConfig.DEBUG变量,用这个就可以控制是否显示log了。强制开关也很简单,在log初始化的最后判断强制开关是否打开,如果打开那么就覆盖之前的显示设置,直接显示log。转为代码就是这样:

  1. public class BaseApplication extends Application {
  2. // 定义是否是强制显示log的模式
  3. protected static final boolean LOG = false;
  4. @Override
  5. public void onCreate() {
  6. super.onCreate();
  7. L.init() // default PRETTYLOGGER or use just init()
  8. //.setMethodCount(2); // default 2
  9. //.hideThreadInfo() // default shown
  10. .setMethodOffset(1); // default 0
  11. // 在debug下,才显示log
  12. L.init().setLogLevel(BuildConfig.DEBUG ? LogLevel.FULL : LogLevel.NONE);
  13. // 如果是强制显示log,那么无论在什么模式下都显示log
  14. if (BaseApplication.LOG) {
  15. L.init().setLogLevel(LogLevel.FULL);
  16. }
  17. }
  18. }