Fork me on GitHub

Kotlin的LogUtil

最近在撸东西,调试的时候用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反馈了,在不久的将来应该会修复。

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
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
}


}