Android开发中,日志定制化打印是很重要的,下面是一种Kotlin日志打印封装,不需要手动每个类中定义TAG了,只要使用下面loge、logv、logd等,让代码自动获取当前类名进行输出TAG。
懒人做法。
正文
代码1
只支持kotlin
import android.util.Log import kotlin.reflect.KClass private const val DEFAULT_TAG = "BiuApp_"//自定义 private const val MAX_TAG_LENGTH = 23 // 标记类,用于动态获取当前文件的包名 private class Pkg private val SELF_PACKAGE: String = Pkg::class.java.`package`?.name ?: "" private val SKIP_PREFIXES = listOf( SELF_PACKAGE, "kotlin.", "kotlinx.", "java.", "javax.", "sun.", "android.", "dalvik.", "com.android." ) /** * 获取安全的 Tag(纯泛型解析,零性能开销) */ fun <T : Any> callerTag(clz: KClass<T>? = null): String { clz?.qualifiedName?.let { className -> if (!SKIP_PREFIXES.any { className.startsWith(it) }) { val simpleName = className.substringBefore("$").substringAfterLast('.') if (simpleName.isNotEmpty()) { val fullTag = DEFAULT_TAG + simpleName // 确保 Tag 不超过 Android 的 23 字符限制 return if (fullTag.length > MAX_TAG_LENGTH) fullTag.take(MAX_TAG_LENGTH) else fullTag } } } // 兜底默认 Tag return DEFAULT_TAG } // ================= 扩展函数封装 ================= inline fun <reified T : Any> T.logv(msg: String, tr: Throwable? = null) { Log.v(callerTag(T::class), msg, tr) } inline fun <reified T : Any> T.logd(msg: String, tr: Throwable? = null) { Log.d(callerTag(T::class), msg, tr) } inline fun <reified T : Any> T.logi(msg: String, tr: Throwable? = null) { Log.i(callerTag(T::class), msg, tr) } inline fun <reified T : Any> T.logw(msg: String, tr: Throwable? = null) { Log.w(callerTag(T::class), msg, tr) } inline fun <reified T : Any> T.loge(msg: String, tr: Throwable? = null) { Log.e(callerTag(T::class), msg, tr) }
代码2
支持kotlin和java
import android.util.Log import kotlin.reflect.KClass private const val DEFAULT_TAG = "BiuApp_"//自定义 private const val MAX_TAG_LENGTH = 23 // 标记类,用于动态获取当前文件的包名 private class Pkg private val SELF_PACKAGE: String = Pkg::class.java.`package`?.name ?: "" private val SKIP_PREFIXES = listOf( SELF_PACKAGE, "kotlin.", "kotlinx.", "java.", "javax.", "sun.", "android.", "dalvik.", "com.android." ) /** * 获取安全的 Tag(纯泛型解析,零性能开销) */ fun <T : Any> callerTag(clz: KClass<T>? = null): String { clz?.qualifiedName?.let { className -> if (!SKIP_PREFIXES.any { className.startsWith(it) }) { val simpleName = className.substringBefore("$").substringAfterLast('.') if (simpleName.isNotEmpty()) { val fullTag = DEFAULT_TAG + simpleName // 确保 Tag 不超过 Android 的 23 字符限制 return if (fullTag.length > MAX_TAG_LENGTH) fullTag.take(MAX_TAG_LENGTH) else fullTag } } } // 兜底默认 Tag return DEFAULT_TAG } // ================= 扩展函数封装 ================= inline fun <reified T : Any> T.logv(msg: String, tr: Throwable? = null) { Log.v(callerTag(T::class), msg, tr) } inline fun <reified T : Any> T.logd(msg: String, tr: Throwable? = null) { Log.d(callerTag(T::class), msg, tr) } inline fun <reified T : Any> T.logi(msg: String, tr: Throwable? = null) { Log.i(callerTag(T::class), msg, tr) } inline fun <reified T : Any> T.logw(msg: String, tr: Throwable? = null) { Log.w(callerTag(T::class), msg, tr) } inline fun <reified T : Any> T.loge(msg: String, tr: Throwable? = null) { Log.e(callerTag(T::class), msg, tr) } // ================= Java 友好顶层函数 ================= // Java 中通过 LogKt.xxx(...) 调用;TAG 自动取调用者类名。 fun logv(msg: String) { Log.v(callerTag(Throwable().stackTrace[1].className), msg) } fun logd(msg: String) { Log.d(callerTag(Throwable().stackTrace[1].className), msg) } fun logi(msg: String) { Log.i(callerTag(Throwable().stackTrace[1].className), msg) } fun logw(msg: String) { Log.w(callerTag(Throwable().stackTrace[1].className), msg) } fun loge(msg: String) { Log.e(callerTag(Throwable().stackTrace[1].className), msg) } /** 带 Throwable 的重载,对应 AppLog.e(msg, tr) */ fun loge(msg: String, tr: Throwable) { Log.e(callerTag(Throwable().stackTrace[1].className), msg, tr) } /** 仅 Throwable(msg 取异常信息),对应 AppLog.e(tr) */ fun loge(tr: Throwable) { Log.e(callerTag(Throwable().stackTrace[1].className), tr.message ?: "", tr) } private fun callerTag(className: String): String { if (className.isEmpty()) return DEFAULT_TAG val simple = className.substringBefore("$").substringAfterLast('.') val full = DEFAULT_TAG + simple return if (full.length > MAX_TAG_LENGTH) full.take(MAX_TAG_LENGTH) else full }

