Android开发规范:日志
Log对于开发者定位问题来说是一个必不可少的工具。开发人员需要通过Log提供的信息,比如Crash异常,能够定位异常类型以及异常的发生代码位置;或者查看输出的内容是否达到期望;亦或者通过Log提供的信息能够看到整个信息的交互流程。
因此拥有一个快捷便利有效的Log输出工具是整个项目必不可少的一部分。
1. 现有的系统Log
2018-11-27 20:50:00.614 29110-29110/com.demo D/ActivityThread: Added TimaKeyStore provider
格式:timestamp PID TID log-level log-tag
timestamp | PID | TID | package name | log-level | log-tag |
---|---|---|---|---|---|
时间戳 | 进程id | 线程id | 包名 | 日志类型 | 日志tag |
2. 改进的Log工具
系统提供的日志虽然已经具备了基本的信息,但是我们可以改进现有的Log功能。
比如提供Log打印类名、方法名、行数。
这样我们直接Ctrl + L输入行数就可以跳转到Log输出的位置,加快问题定位速度。
public class LogUtil {
public static String customTagPrefix = "ddnosh";
private static final boolean isDebug=true;
private LogUtil() {
}
private static String generateTag() {
StackTraceElement caller = new Throwable().getStackTrace()[2];
String tag = "%s.%s(Line:%d)";
String callerClazzName = caller.getClassName();
callerClazzName = callerClazzName.substring(callerClazzName.lastIndexOf(".") + 1);
tag = String.format(tag, callerClazzName, caller.getMethodName(), caller.getLineNumber());
tag = TextUtils.isEmpty(customTagPrefix) ? tag : customTagPrefix + ":" + tag;
return tag;
}
public static void d(String content) {
if (!isDebug) return;
String tag = generateTag();
Log.d(tag, content);
}
public static void d(String content, Throwable tr) {
if (!isDebug) return;
String tag = generateTag();
Log.d(tag, content, tr);
}
public static void e(String content) {
if (!isDebug) return;
String tag = generateTag();
Log.e(tag, content);
}
public static void e(String content, Throwable tr) {
if (!isDebug) return;
String tag = generateTag();
Log.e(tag, content, tr);
}
public static void i(String content) {
if (!isDebug) return;
String tag = generateTag();
Log.i(tag, content);
}
public static void i(String content, Throwable tr) {
if (!isDebug) return;
String tag = generateTag();
Log.i(tag, content, tr);
}
public static void v(String content) {
if (!isDebug) return;
String tag = generateTag();
Log.v(tag, content);
}
public static void v(String content, Throwable tr) {
if (!isDebug) return;
String tag = generateTag();
Log.v(tag, content, tr);
}
public static void w(String content) {
if (!isDebug) return;
String tag = generateTag();
Log.w(tag, content);
}
public static void w(String content, Throwable tr) {
if (!isDebug) return;
String tag = generateTag();
Log.w(tag, content, tr);
}
public static void w(Throwable tr) {
if (!isDebug) return;
String tag = generateTag();
Log.w(tag, tr);
}
public static void wtf(String content) {
if (!isDebug) return;
String tag = generateTag();
Log.wtf(tag, content);
}
public static void wtf(String content, Throwable tr) {
if (!isDebug) return;
String tag = generateTag();
Log.wtf(tag, content, tr);
}
public static void wtf(Throwable tr) {
if (!isDebug) return;
String tag = generateTag();
Log.wtf(tag, tr);
}
}
3. 从日志模块谈扩展性
日志作为一个基础模块功能,应当具备良好的扩展性。
所谓的扩展性,比如市面上有很多第三方日志工具,比如Log4J, Logger,Logback等,很多项目都会选择其中一个作为项目的日志模块,或者一个团队的多个项目都用一套固定的日志模块。
但是从通用性的角度考虑,Project应该和Module减少耦合性,也就是说一个Project可以在任何时候都能随时随地更换Module,而不需要更改Project中的代码,通过配置文件进行动态更新。
比如我们又找到了一个性能更好的Log系统,能够提升日志打印、保存效率,并且还有更详细的打印日志,那么我们该怎么替换呢?那是不是要到Project里面一个个的将旧的API接口替换成新的API接口呢?
那这样的来说,Project其实是和某一个Module的API强耦合了。
这有点像电脑的USB接口,我们需要外接存储设备,那么USB接口就是一个连接电脑和外置存储设备之间的桥梁,我们可以插入优盘,如果觉得容量小了,那么我们可以拔掉优盘,插上外置的移动硬盘,然后电脑本身不需要做任何改动,就可以用上外置的移动硬盘。
这里,电脑 = Project,USB = 协议,外置设备(优盘、移动硬盘) = Module
在《阿里巴巴Java开发手册》里面有对Log接入的明确规定:
( ( 二) ) 日志规约
1.【强制】应用中不可直接使用日志系统 (Log 4 j 、 Logback) 中的 API ,而应依赖使用日志框架
SLF4J 中的 API ,使用门面模式的日志框架,有利于维护和各个类的日志处理方式统一。
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(Abc.class);
LoggerFactory其实就是一个工厂模式中的对象,我们后续会针对利用工厂模式解除Project和Module之间的耦合性做专门的讲解。
上一篇: Android应用安全防护的点点滴滴
下一篇: 求Π的近似值 (c语言)
推荐阅读