在开发的时候Log并不为程序员所重视,所以常常到了Debug的时候,开始胡乱的打Log,最后Bug是调完了,代码是彻底混乱了。
真正的Log就应该是在思路最清楚的时候打的,无论是对自己还是为后面的要看自己代码的人来说都是福音。
而在Android开发中常用的Logcat()和System.out.println()对于小型的应用是足够了,但是对于规模稍大,代码稍多的项目来说,我要不仅要考虑Log的
等级,还要考虑Log的记录,并在发布时去掉调试的标记。这时候上面两个函数就有点捉襟见肘了。
在这里,我们引入slf4j-api-xxx.jar+logback-android-xxx.jar这两个开源日志架构,来帮助我们规范开发,提高效率。
GitHub:https://github.com/tony19/logback-android GitHub地址
这里附带提一下log4j,java中最为常用的Log框架,但是到后面已不再更新,因为作者根据自己多年的框架经验重新写的,无论在效率还是可扩展性上,都有了极大的提高。
而与Log4j的比较,可以看看这篇文章:
Reasons to switch to logback from log4j
unique and rather useful features
那么现在日志是如何组织架构的呢,在上面的包名中我们可以看出,一个带了api,而一个写了平台android,也就是说前一个是要实现Log框架必须要实现的接口,而真正的实现在后面的jar包时,了解设计模式的都知道,依赖倒转原则,就是针对接口编程,而不是对实现编程,
依赖倒置原则:
高层模块不应依赖低层模块,两个都应依赖抽象。
抽象不应该依赖细节,细节应该依赖抽象。
所以我们对不android平台只要更换logback-android的实现包,针对桌面平台也可使用logback-classic ,logback-core等包
首先来看看标准的一个配置文件:
<configuration>
<property name="LOG_DIR" value="/data/data/com.example/files" />
<!-- Create a logcat appender -->
<appender name="logcat" class="ch.qos.logback.classic.android.LogcatAppender">
<encoder>
<pattern>%msg</pattern>
</encoder>
</appender>
<!-- Create a file appender for TRACE-level messages -->
<appender name="TraceLog" class="ch.qos.logback.core.FileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>TRACE</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<file>${LOG_DIR}/trace.log</file>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- Create a file appender for DEBUG-level messages -->
<appender name="DebugLog" class="ch.qos.logback.core.FileAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<file>${LOG_DIR}/debug.log</file>
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- Write TRACE messages from class A to its own log -->
<logger name="com.example.A" level="TRACE">
<appender-ref ref="TraceLog" />
</logger>
<!-- Write DEBUG messages from class B to its own log -->
<logger name="com.example.B" level="DEBUG">
<appender-ref ref="DebugLog" />
</logger>
<!-- Write INFO (and higher-level) messages to logcat -->
<root level="INFO">
<appender-ref ref="logcat" />
</root>
</configuration>
logback-android支持通过xml、groovy、代码三种形式来配置日志参数,xml文件的位置是${project-root}/assets/logback.xml,也可以在AndroidManifest.xml里配置。Groovy是新加的一种文件形式,可以作为java平台的脚本语言来使用。当然也可以在代码中动态的进行配置。
通过上面配置样例中,我们可以发现其主要可以分为Appender-Encoder-Layout-Filters,这几个层次组成的。
而logback中允许日志输入至多个地方,像控制台、文件、数据库等,而一个输入地就是一个Appender,在安卓中我们需要有控制台的输出,也需要有日志文件的记录,所以定义这个Appender是至少的。在Appender中处理的就是接收logback从系统发来的信息流交给其处理。接下去的格式化的活就交给encoder来处理。
比如 <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> 有点像c语言里的printf中的格式化参数,可以自定义需要以怎样的方式输出。
这里是表示输出中要包括时间、线程、等级、信息的来源和信息,这里用的是Pattern,当然也可以用Layout来表示,其作用是将输入的事件信息转换成String类型的值。
Filter顾名思义就是表示过滤器,有点像Logcat里一样,我们可以通过包名来过滤,可以通过错误等级来过滤,方便我们查找需要的信息。
如果相在AndroidManifest.xml里设置可以参照
<logback>
<configuration>
<appender
name="LOGCAT"
class="ch.qos.logback.classic.android.LogcatAppender" >
<tagEncoder>
<pattern>%logger{0}</pattern>
</tagEncoder>
<encoder>
<pattern>[ %thread ] %msg%n</pattern>
</encoder>
</appender>
<root level="WARN" >
<appender-ref ref="LOGCAT" />
</root>
</configuration>
</logback>
由于log最先查找的配置文件就是${project-root}/assets/logback.xml
要让其从其它地方寻找可以如下定义:
<configuration>
<includes>
<include file="/sdcard/foo.xml"/>
<include resource="assets/config/test.xml"/>
<include resource="AndroidManifest.xml"/>
</includes>
</configuration>
即通过Include来标记配置位置,所以使用十分灵活。
<root level="INFO">
<appender-ref ref="logcat" />
</root>
这个是控制日志开发的设置,ref值表示我们要开户的通道,这里表示仅输入至logcat控制台中,也可以文件、控制台一起开启,特别适合在没连电脑的情况下日志的记录。
最后调用仅需要在要打log的代码中输入:
// SLF4J
Logger log = LoggerFactory.getLogger(MainActivity.class);
log.info("hello world");
可以发现,调用的全是接口,实现交给LoggerFactory工厂来实例化。
所以说,通过这个架构来学习框架非常好,是个十分好的应用例子。
后面有时间,再分析一下他的实现框架,当然对于应用来说掌握到这里差不多就可以以不变应万变了。