优点:
- 代码级禁用,DEBUG才有日志可以看到
- isLoggable运行时拦截
- 零泄露风险
- 边框包裹,自动格式化
- 精准定位,点击跳转
- 使用简单,动态调用和TAG
- 零开销潜力,内存友好
下面是类的内容:
import android.util.Log
import com.orhanobut.logger.Logger
import com.orhanobut.logger.PrettyFormatStrategy
import your.package.app.BuildConfig
/**
* 日志工具类
* 核心规则:Release包完全禁用所有日志输出,Debug包正常输出格式化日志
* 支持日志级别:VERBOSE/DEBUG/INFO/WARN/ERROR
* 支持场景:无Tag日志、自定义Tag、带异常堆栈、可变参数格式化
*/
object LogUtils {
// 全局默认Tag(可根据项目修改)
private const val DEFAULT_TAG = "MY_APP"
/**
* 初始化日志配置(在App.kt的onCreate中调用)
*/
fun init() {
if (BuildConfig.DEBUG) {
// Debug模式:初始化格式化日志配置
val formatStrategy = PrettyFormatStrategy.newBuilder()
.showThreadInfo(false) // 显示线程信息
.methodCount(2) // 显示调用方法行数(2行足够定位)
.methodOffset(1) // 方法偏移量
.tag(DEFAULT_TAG) // 默认Tag
.build()
Logger.addLogAdapter(object : com.orhanobut.logger.AndroidLogAdapter(formatStrategy) {
// 仅Debug模式允许日志输出
override fun isLoggable(priority: Int, tag: String?): Boolean = BuildConfig.DEBUG
})
} else {
// Release模式:移除所有日志适配器,确保无日志输出
Logger.clearLogAdapters()
}
}
// ====================== 基础日志方法(无Tag,使用默认Tag) ======================
fun v(message: String, vararg args: Any) {
if (BuildConfig.DEBUG) Logger.v(message, *args)
}
fun d(message: String, vararg args: Any) {
if (BuildConfig.DEBUG) Logger.d(message, *args)
}
fun i(message: String, vararg args: Any) {
if (BuildConfig.DEBUG) Logger.i(message, *args)
}
fun w(message: String, vararg args: Any) {
if (BuildConfig.DEBUG) Logger.w(message, *args)
}
fun e(message: String, vararg args: Any) {
if (BuildConfig.DEBUG) Logger.e(message, *args)
}
// ====================== 带异常堆栈的日志(无Tag) ======================
fun e(throwable: Throwable, message: String, vararg args: Any) {
if (BuildConfig.DEBUG) Logger.e(throwable, message, *args)
}
// ====================== 自定义Tag的日志方法 ======================
fun v(tag: String, message: String, vararg args: Any) {
if (BuildConfig.DEBUG) Logger.t(tag).v(message, *args)
}
fun d(tag: String, message: String, vararg args: Any) {
if (BuildConfig.DEBUG) Logger.t(tag).d(message, *args)
}
fun i(tag: String, message: String, vararg args: Any) {
if (BuildConfig.DEBUG) Logger.t(tag).i(message, *args)
}
fun w(tag: String, message: String, vararg args: Any) {
if (BuildConfig.DEBUG) Logger.t(tag).w(message, *args)
}
fun e(tag: String, throwable: Throwable, message: String, vararg args: Any) {
if (BuildConfig.DEBUG) Logger.t(tag).e(throwable, message, *args)
}
fun e(tag: String, message: String, vararg args: Any) {
if (BuildConfig.DEBUG) Logger.t(tag).e(message, *args)
}
// ====================== 兼容原生Log的极简方法(可选) ======================
/**
* 极简Debug日志(自动取调用类名作为Tag)
*/
fun simpleD(message: String) {
if (BuildConfig.DEBUG) {
val tag = getCallerClassName()
Log.d(tag, message)
}
}
/**
* 极简Error日志(自动取调用类名作为Tag,带异常)
*/
fun simpleE(throwable: Throwable, message: String) {
if (BuildConfig.DEBUG) {
val tag = getCallerClassName()
Log.e(tag, message, throwable)
}
}
/**
* 私有方法:获取调用者的类名(用于simple系列日志的自动Tag)
*/
private fun getCallerClassName(): String {
return try {
// 获取调用栈,定位到LogUtils外部的调用类
val stackTrace = Thread.currentThread().stackTrace
val callerStackIndex = 4 // 栈索引:0=VM,1=Thread,2=getCallerClassName,3=simpleD/E,4=外部调用者
val callerClass = Class.forName(stackTrace[callerStackIndex].className)
callerClass.simpleName // 只取类名(不含包名),简化Tag
} catch (e: Exception) {
DEFAULT_TAG // 异常时使用默认Tag
}
}
/**
* 清空日志(Release模式下无操作)
*/
fun clear() {
if (BuildConfig.DEBUG) Logger.clearLogAdapters()
}
}
在使用之前,需要在Application 中调用:
LogUtils.init()
//记得在Manifest文件中检查是否为自定义的Application
使用示例
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import your.package.app.common.LogUtils // 导入你的日志工具类
class MainActivity : AppCompatActivity() {
private val USER_ID = 1001
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 使用封装后的日志方法,它会在 Debug 包中格式化输出
LogUtils.d("MainActivity 已启动") // 无Tag,使用默认Tag
// 使用带参数的格式化日志
LogUtils.i("用户 %d 正在加载数据...", USER_ID)
// 使用自定义 Tag
LogUtils.w("UI", "Warning: 布局文件加载可能耗时")
// 模拟一个异常日志
try {
// 模拟抛出异常
throw RuntimeException("网络连接失败")
} catch (e: Exception) {
// 输出带异常堆栈的日志
LogUtils.e(e, "数据加载失败,请检查网络!")
}
}
}
最终可能的输出效果:
// LogUtils.d("MainActivity 已启动") 的输出
D/MY_APP: ┌────────────────────────────────────────────────────────
D/MY_APP: │ MainActivity.onCreate (MainActivity.kt:15)
D/MY_APP: ├────────────────────────────────────────────────────────
D/MY_APP: │ MainActivity 已启动
D/MY_APP: └────────────────────────────────────────────────────────
// LogUtils.e(e, "数据加载失败,请检查网络!") 的输出
E/MY_APP: ┌────────────────────────────────────────────────────────
E/MY_APP: │ MainActivity.onCreate (MainActivity.kt:28)
E/MY_APP: ├────────────────────────────────────────────────────────
E/MY_APP: │ RuntimeException: 网络连接失败
E/MY_APP: │ at your.package.app.MainActivity.onCreate(MainActivity.kt:24)
E/MY_APP: │ ... (省略部分堆栈)
E/MY_APP: ├────────────────────────────────────────────────────────
E/MY_APP: │ 数据加载失败,请检查网络!
E/MY_APP: └────────────────────────────────────────────────────────

发表回复