一、概述
在工作过程中,发现一个比较有意思的现象:每个同事都有一个自己的代码库,里面基本都包含一个Log的工具。这充分说明了Log在Android 开发中的重要,不管如何实现,大家都不自觉地按照自己的习惯,完成了一个Log工具。每个开发者都有自己的习惯和特点,在Log工具上的实现大同小异,但如果在同一个项目中加入各自的Log工具,难免产生了重复代码,还可能会造成使用的困扰。一个团队,在基础工具上还是要保持一致,本文尝试实现一个大家都接受,并且能满足大家需求,在使用上还不会造成困扰的,高性能的,可扩展的 Log 框架,项目地址:Logger。
二、Log 需求
- 参考Android自带的Log工具,log有,VERBOSE,DEBUG,INFO,WARN,ERROR,ASSERT六个等级,对应有六个方法(常用):v,d,I,w,e,wtf;
- 可以输出到logcat,也可以输出到文件或其它;
- 可以选择关闭或者打开某个或者所有log;
- 可以自定义增加新的log;
- 输出到logcat的log还可以显示代码行数,点击即可打开这个类文件,并且定位到对应的行;
- 可以上传到后台服务器;
- 其它…
三、定义Logger
从上面的需求,我们可以定义一个ILogger的接口:
public interface ILogger {
int VERBOSE = 2;
int DEBUG = 3;
int INFO = 4;
int WARN = 5;
int ERROR = 6;
int ASSERT = 7;
void v(String tag, String msg);
void d(String tag, String msg);
void i(String tag, String msg);
void w(String tag, String msg);
void e(String tag, String msg);
void enable(boolean enable); // 设置是否可用
void close(); // 关闭这个Logger
void save(); // 保存内存中的Log(文件或其它Log时使用)
}
为了统一log的格式,定义一个抽象Loger类:
public abstract class AbstractLogger implements ILogger {
public static String LEFT_BRACKET = "(";
public static String RIGHT_BRACKET = ")";
public static String SHARP = "#";
public static String COLON = ":";
protected String formatLogMsg(String msg, String fileName, int lineNumber, String methodName) {
StringBuffer buffer = new StringBuffer();
buffer.append(LEFT_BRACKET);
buffer.append(fileName)
.append(COLON).append(lineNumber).append(RIGHT_BRACKET)
.append(SHARP).append(methodName)
.append(COLON).append(msg);
return buffer.toString();
}
protected StackTraceElement getStackTraceElement(int index) {
StackTraceElement[] traceElements = Thread.currentThread().getStackTrace();
StackTraceElement element = traceElements[index];
return element;
}
}
四、具体Logger实现
根据需求,首先我们需要一个可以输出到Logcat,并且可以显示代码行数的logger,可以命名为LogcatLogger,然后还要有一个输出到文件的logger,可以命名为FileLogger。
LogcatLogger
LogcatLogger很简单,就是调用一下系统的Log的对应方法即可,与系统的Log不一样的是,它可以显示代码行数,并且可以定位到具体的类文件,具体实现如下:
import android.util.Log;
import com.bottle.log.AbstractLogger;
public class LogcatLogger extends AbstractLogger {
private boolean isDebuggable = true;
public LogcatLogger() {
}
@Override
public void enable(boolean enable) {
this.isDebuggable = enable;
}
@Override
public void close() {
isDebuggable = false;
}
@Override
public void save() {
}
@Override
public void v(String tag, String msg) {
if (isDebuggable == false) {
return;
}
StackTraceElement element = getStackTraceElement(7);
Log.v(tag, formatLogMsg(msg, element.getFileName(), element.getLineNumber(), element.getMethodName()));
}
@Override
public void d(String tag, String msg) {
if (isDebuggable == false) {
return;
}
StackTraceElement element = getStackTraceElement(7);
Log.d(tag, formatLogMsg(msg, element.getFileName(), element.getLineNumber(), element.getMethodName()));
}
@Override
public void i(String tag, String msg) {
if (isDebuggable == false) {
return;
}
StackTraceElement element = getStackTraceElement(7);
Log.i(tag, formatLogMsg(msg, element.getFileName(), element.getLineNumber(), element.getMethodName()));
}
@Override
public void w(String tag, String msg) {
if (isDebuggable ==