最近在撸东西,调试的时候用Android原生的Log感觉很不爽,打的Log给我一种东倒西歪,凌乱的感觉。于是自己看了一下Blankj大神的Android-Utils库,看了一下他实现的LogUtils,借鉴了一下,简单的封装了一个在Kotlin中可以正确使用的LogUtil。不过话说讲道理,有扩展,Util这种东西还是可以尽量不用的,但是我有点不清楚Log这玩意该扩展给谁呢,Any?所以还是写了一个LogUtil……
打印效果
最后直接放一下打印Log的样子,这里只放出i级别的日志:
处理了日志比较长的时候的情况,点击log中蓝色的字可以跳转到代码中的相应位置,各位如果感兴趣是怎么实现的,可以直接看我代码(当然了,我也是看别人的才知道怎么去实现,哈哈)。
Blankj大神的LogUtils有一个问题,就是代码中获取代码文件的时候写死了.java结尾,所以在kotlin以.kt结尾的时候,就无法正确的跳转到代码里(版本号:1.8.3),当然了,我已经跟Blankj反馈了,在不久的将来应该会修复。
完整代码
import android.util.Log
import java.util.*
/**
* Created by xiasuhuei321 on 2017/9/1.
* author:luo
* e-mail:xiasuhuei321@163.com
*/
object LogUtil {
private val MIN_STACK_OFFSET = 3
var defaultTag = "LogUtil"
private val lineSeparator = System.getProperty("line.separator", "/n")
val V = Log.VERBOSE
val D = Log.DEBUG
val I = Log.INFO
val W = Log.WARN
val E = Log.ERROR
val A = Log.ASSERT
private val TOP_BORDER = "╔═══════════════════════════════════════════════════════════════════════════════════════════════════"
private val LEFT_BORDER = "║ "
private val BOTTOM_BORDER = "╚═══════════════════════════════════════════════════════════════════════════════════════════════════"
private val MAX_LEN = 1000
var open = true
private fun processTagAndHead(): String {
val elements = Thread.currentThread().stackTrace
val offset = getStackOffset(elements)
val targetElement = elements[offset]
val head = Formatter()
.format("%s [%s(%s:%d)]",
"In Thread: " + Thread.currentThread().name,
targetElement.methodName,
targetElement.fileName,
targetElement.lineNumber)
return head.toString()
}
private fun processMsgBody(msg: String, flag: Int, tag: String = defaultTag) {
printTop(flag, tag)
// 首先打印调用信息
printLog(flag, tag)
val lineCount = msg.length / MAX_LEN
if (lineCount == 0) {
printLog(flag, tag, msg)
} else {
var index = 0
var i = 0
while (true) {
printLog(flag, tag, msg.substring(index, index + MAX_LEN))
index += MAX_LEN
if ((++i) >= lineCount)
break
}
}
printBottom(flag, tag)
}
fun getStackOffset(trace: Array<StackTraceElement>): Int {
var i = MIN_STACK_OFFSET
while (i < trace.size) {
val e = trace[i]
val name = e.className
if (name != LogUtil::class.java.name) {
return i
}
i++
}
return 2
}
/* 虽然 kotlin 有默认值这种操作,但是 Log.i(tag,msg) 这种比较符合平时的操作,所以还是提供类似的重载,
* 而非 LogUtil.i(msg: String,tag: String = defaultTAG) 这种带默认值参数的方法 */
fun v(msg: String) {
v(defaultTag, msg)
}
fun i(msg: String) {
i(defaultTag, msg)
}
fun d(msg: String) {
d(defaultTag, msg)
}
fun w(msg: String) {
w(defaultTag, msg)
}
fun e(msg: String) {
e(defaultTag, msg)
}
fun v(tag: String, msg: String) {
if (!open) {
return
}
processMsgBody(msg, V, tag)
}
fun i(tag: String, msg: String) {
if (!open) {
return
}
processMsgBody(msg, I, tag)
}
fun d(tag: String, msg: String) {
if (!open) {
return
}
processMsgBody(msg, D, tag)
}
fun w(tag: String, msg: String) {
if (!open) {
return
}
processMsgBody(msg, W, tag)
}
fun e(tag: String, msg: String) {
if (!open) {
return
}
processMsgBody(msg, E, tag)
}
fun printLog(flag: Int, tag: String, msg: String = processTagAndHead()) {
Log.println(flag, tag, LEFT_BORDER + msg)
}
fun printBottom(flag: Int, tag: String) {
Log.println(flag, tag, BOTTOM_BORDER)
}
fun printTop(flag: Int, tag: String) {
Log.println(flag, tag, TOP_BORDER)
}
fun closeLog() {
this.open = false
}
}