Android-Logcat & Timber

1,042 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

Logcat的缺陷

Logcat是Android平台默认日志工具, 方便且好用. 但它也有不足够之处.

Logcat日常使用中需要注意的事项:

  • Logcattagmessage在Android 26之前有长度的限制:
  • 在Android 26之前, tag长度最大为23个字符, 超出的会自动截取丢掉; message的最大长度为4096个字符, 超出的会被自动丢掉.

而在Android 26之后, tag的长度限制被取消掉, 但是message的长度限制还在. 这就存在当日志消息太长时, 会导致超过长度限制之后的消息会丢失.

Timer: Logcat的完美替代方案

Logcat的替代解决方案是: Timber, 大神jake wharton的偶然而为的杰作.

Timber是Android平台日志工具, 基于Android常规的Log类, 提供了小但可扩展的API.

日志行为可以通过添加Tree实例进行添加. 你可以通过调用Timber.plant函数安装新的实例. Tree的安装应该尽可能的早. 应用的onCreate是最符合逻辑的地方.

DebugTree会自动的找出被调用类并且使用该类的名字作为标签. 因为标签比较多样, 当和像Pidcat这样的日志阅读器耦合时, 它工作的非常良好.

默认情况下没有任何Tree实现是安装了的, 因为每一次在生产中打印日志, 就会出现很大问题.

  • Timber提供了接口去扩展并接入别的日志工具.
/** Return whether a message at `priority` should be logged. */
@Deprecated("Use isLoggable(String, int)", ReplaceWith("this.isLoggable(null, priority)"))
protected open fun isLoggable(priority: Int) = true

/** Return whether a message at `priority` or `tag` should be logged. */
protected open fun isLoggable(tag: String?, priority: Int) = isLoggable(priority)

/**
 * Write a log message to its destination. Called for all level-specific methods by default.
 *
 * @param priority Log level. See [Log] for constants.
 * @param tag Explicit or inferred tag. May be `null`.
 * @param message Formatted log message.
 * @param t Accompanying exceptions. May be `null`.
 */
protected abstract fun log(priority: Int, tag: String?, message: String, t: Throwable?)

同时默认实现了LogcatTree来使用Logcat打印日志.

  • LogcatTree对于log的处理: 在Android 26之前自动截取前23个字符, 避免了IllegalArgumentException. 在Android 26之后, 维持了tag的原样.

  • LogcatTree对于message的处理: 如果message的长度超过了4096, 会将message每4096个字符打印一下, 直到message的结束.

  • Timber是线程安全的, 通过@Volatile private var treeArray = emptyArray<Tree>()synchronized(trees)实现的诸如Timber#plant(Tree), Timer#forest(), Timer#uproot(Tree)Timer#uprootAll()等函数来保证.

  • Timber也默认提供了Lint工具来检测关于格式化String相关的代码, 诸如TimberArgCount, TimberArgTypes, TimberTagLength, LogNotTimber, StringFormatInTimber, BinaryOperationInTimber, TimberExceptionLogging.

Timer通过在Application#onCreate中调用Timer#plant(Tree)或者Timer#plant(varargs Tree)来植入1个或多个Tree来打印日志.