Kotlin 一劳永逸实现 TAG

news2024/11/20 10:32:28

1 TAG 经典写法

        对于 Android 开发,当我们需要在类中打印 Log 时,通常在Java中会这么定义一个 TAG:

    private static final String TAG = "TestClass";

        或者不具体指定名字:

    private static final String TAG = TestClass.class.getSimpleName();

那么,在 Kotlin 中

        我们通常会这样定义:

    private val TAG = TestClass::class.java.simpleName

        或者采用类似于 Java 的静态方式实现:

    companion object {
        private val TAG = TestClass::class.java.simpleName
    }

        甚至还加上 @JvmField 注解,方便外部调用:

    companion object {
        @JvmField val TAG: String = TestClass::class.java.simpleName
    }

        companion object 的属性/方法会产生额外的 static final 的同伴类实例,因此在性能和内存方面都很糟糕,所以大可不必将 TAG 放在 companion object,下面2张图或许可以告诉你一些东西:

2 TAG 一劳永逸

        以上方式,都需要在每个类定义相应的 TAG,是比较繁琐的。

        那么,在 Kotlin 中可以通过扩展函数统一声明 TAG,避免在每个类中定义相应的 TAG。

我们可以通过如下两种方式实现:

        方式一:

val Any.TAG: String
    get() {
        return javaClass.simpleName
    }

        方式二:

inline val <reified T> T.TAG: String
    get() = T::class.java.simpleName

3 TAG 持续优化

3.1 TAG 长度限制

        我们知道,从API 24开始,TAG 就没有长度限制,所以需要对长度做个兼容:

        方式一:

val Any.TAG: String
    get() {
        val name = javaClass.simpleName
        return if (name.length <= 23 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) name
        else name.substring(0, 23)
    }

        方式二: 

inline val <reified T>T.TAG: String
    get() {
        val name = T::class.javaClass.simpleName
        return if (name.length <= 23 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) name
        else name.substring(0, 23)
    }

3.2 匿名内部类的 TAG

        匿名内部类长度较长,我们可以使用 name 代替 simpleName 去解析相应 TAG:

        方式一:

val Any.TAG: String
    get() {
        return if (!javaClass.isAnonymousClass) {
            val name = javaClass.simpleName
            if (name.length <= 23 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) name
            else name.substring(0, 23)
        } else {
            val name = javaClass.name
            if (name.length <= 23 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) name
            else name.substring(name.length - 23, name.length)
        }
    }

        方式二: 

inline val <reified T> T.TAG: String
    get() {
        return if (!T::class.javaClass.isAnonymousClass) {
            val name = T::class.javaClass.simpleName
            if (name.length <= 23 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) name
            else name.substring(0, 23)
        } else {
            val name = T::class.javaClass.name
            if (name.length <= 23 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) name
            else name.substring(name.length - 23, name.length)
        }
    }

3.3 类被混淆的 TAG

        当类被混淆时,simpleName 不是一个好的解决方案,例如 MyActivity 可能会变成 M,此刻或许在类中显示声明 TAG 会更好:

    private val TAG = "TestClass"

4 推荐写法

        两种方式差别不大,由于作者更喜欢方式二内联实现,所以本文推荐方式二,实现一劳永逸的 TAG。

inline val <reified T> T.TAG: String
    get() {
        return if (!T::class.javaClass.isAnonymousClass) {
            val name = T::class.javaClass.simpleName
            if (name.length <= 23 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) name
            else name.substring(0, 23)
        } else {
            val name = T::class.javaClass.name
            if (name.length <= 23 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) name
            else name.substring(name.length - 23, name.length)
        }
    }


走一段令人留恋的路,做一个不负自己的人

本文 Demo 代码参考参见后文


【Extensions.kt 文件】

package com.agg.utils

import android.os.Build

/**
 * Description:
 * CreateDate:     2023/6/20 16:12
 * Author:         agg
 */
class Extensions {}

//     private static final String TAG = "TestClass";

//     private static final String TAG = TestClass.class.getSimpleName();

//     private val TAG = TestClass::class.java.simpleName

//      companion object {
//          private val TAG = TestClass::class.java.simpleName
//      }

//      companion object {
//          @JvmField val TAG: String = TestClass::class.java.simpleName
//      }

//val Any.TAG: String
//    get() {
//        return javaClass.simpleName
//    }

//inline val <reified T> T.TAG: String
//    get() = T::class.java.simpleName

//val Any.TAG: String
//    get() {
//        val name = javaClass.simpleName
//        return if (name.length <= 23 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) name
//        else name.substring(0, 23)
//    }

//inline val <reified T>T.TAG: String
//    get() {
//        val name = T::class.javaClass.simpleName
//        return if (name.length <= 23 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) name
//        else name.substring(0, 23)
//    }

//val Any.TAG: String
//    get() {
//        return if (!javaClass.isAnonymousClass) {
//            val name = javaClass.simpleName
//            if (name.length <= 23 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) name
//            else name.substring(0, 23)
//        } else {
//            val name = javaClass.name
//            if (name.length <= 23 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) name
//            else name.substring(name.length - 23, name.length)
//        }
//    }

inline val <reified T> T.TAG: String
    get() {
        return if (!T::class.javaClass.isAnonymousClass) {
            val name = T::class.javaClass.simpleName
            if (name.length <= 23 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) name
            else name.substring(0, 23)
        } else {
            val name = T::class.javaClass.name
            if (name.length <= 23 || Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) name
            else name.substring(name.length - 23, name.length)
        }
    }

【参考文档】在Kotlin中定义log TAG常量的最佳方式是什么?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/669507.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java粮油质量管控防伪溯源系统源码 粮油MES源码

Java粮油质量管控防伪溯源系统源码&#xff0c; 粮油MES源码&#xff0c;有演示&#xff0c;有源码。 一、全生命周期的追踪与溯源 &#xff08;1&#xff09;通过一物一码管理生产销售、追踪包装关联&#xff0c;配送管理及终端查询来实现窜货预警&#xff0c;及时处理问题&…

(一)rstudio容器用户配置root权限,安装conda

1、查看运行中的容器&#xff1a;docker ps 2、进入容器&#xff1a;docker exec -it my_rstudio /bin/bash 3、安装工具&#xff1a;apt-get install 4、查看权限配置文件&#xff1a;cat /etc/sudo 5、查看确认用户(rstudio)&#xff1a;cat /etc/passwd | cut -d: -f1 ro…

判断给定数据中是否存在True只要存在一个True结果为Turenp.sometrue()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 判断给定数据中是否存在True 只要存在一个True结果为Ture np.sometrue() 选择题 下列说法错误的是? import numpy as np a np.array([False, False, True]) print("【显示】a "…

三年时间打磨,MeterSphere v2.10 LTS版本给测试用户带来的价值

2023年5月&#xff0c;MeterSphere开源持续测试平台&#xff08;https://github.com/metersphere&#xff09;发布了v2.10 LTS版本。这是这个开源项目自2020年2月写下第一行代码后发布的第三个LTS版本。 在软件行业&#xff0c;LTS&#xff08;即Long Term Support&#xff09…

SQL太慢如何进行优化

1.慢SQL优化思路。 慢查询日志记录慢SQL explain分析SQL的执行计划 profile 分析执行耗时 Optimizer Trace分析详情 确定问题并采用相应的措施 1.1 慢查询日志记录慢SQL 如何定位慢SQL呢、我们可以通过慢查询日志来查看慢SQL。默认的情况下呢&#xff0c;MySQL数据库是不开…

C盘文件恢复怎么做?数据恢复,就看这4招!

我一般比较重要的文件都会保存到c盘中。最近电脑有点卡顿&#xff0c;想清理一下不需要的文件&#xff0c;但不小心删除了一个很重要的文件&#xff0c;c盘删除的文件还能恢复吗&#xff1f;谁可以帮我想想c盘中的文件如何恢复呢&#xff1f; C盘对于电脑来说是个很重要的磁盘&…

Linux教程——Vim移动光标快捷键汇总

Vim 文本编辑器中&#xff0c;最简单的移动光标的方式是使用方向键&#xff0c;但这种方式的效率太低&#xff0c;更高效的方式使用快捷键。 Vim 移动光标常用的快捷键及其功能如下面各表所示&#xff0c;需要注意的是&#xff0c;表中所有的快捷键都在命令模式&#xff08;默…

安卓蓝牙L2CAP协议简介及报文格式

概述 逻辑链路控制和适配协议&#xff08;Logical Link Control and Adaptation Protocol&#xff0c;L2CAP&#xff09;是蓝牙的核心协议&#xff0c;负责适配基带中的上层协议。它同链路管理器并行工作&#xff0c;向上层协议提供定向连接的和无连接的数据业务。L2CAP具有分…

彻底理解SQL中的JOIN

数据准备 -- 建表语句 CREATE TABLE tbl_dept (id int(11) NOT NULL AUTO_INCREMENT,deptName varchar(30) DEFAULT NULL,locAdd varchar(40) DEFAULT NULL,PRIMARY KEY (id) ) ENGINEInnoDB AUTO_INCREMENT1 DEFAULT CHARSETutf8;CREATE TABLE tbl_emp (id int(11) NOT NULL …

【运维知识进阶篇】zabbix5.0稳定版详解4(用脚本自定义监控项+监控MySQL状态信息)

我们在做自定义监控项的时候&#xff0c;一个一个取比较麻烦&#xff0c;取出一个数值&#xff0c;就要把该数值相关信息以一定格式写入/etc/zabbix/zabbix_agentd.d/下的配置文件里&#xff0c;当遇到需要取很多数值的时候&#xff0c;这样的操作会很繁琐&#xff0c;当有一种…

前端程序员必须要知道的跨域问题以及解决方法

大厂面试题分享 面试题库 前后端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 web前端面试题库 VS java后端面试题库大全 前言 前端程序员必须要知道的跨域问题以及解决方法 node 代理 原理 同源策略发生在浏览…

基于Java+socket实现多线程聊天室-控制台版

基于Javasocket实现多线程聊天室-控制台版 一、系统介绍二、功能展示1.运行效果 三、代码展示四、其它1.其他系统实现2.获取源码 一、系统介绍 首先启动server端&#xff0c;然后启动client端。任意一个client发送给server的消息都将会被转发给所有在线的client&#xff0c;实…

C++基础(16)——STL常用算法(排序、拷贝和集合)

前言 本文介绍了C中STL常用排序、拷贝和集合算法 9.3&#xff1a;常见的排序算法&#xff08;sort、random_shuffle、merge、reverse&#xff09; 9.3.1&#xff1a;sort 9.3.2&#xff1a;random_shuffle 将容器中的数据位置重新打乱&#xff0c;可以配合随机数种子使用 9…

【Java】Java核心要点总结 69

文章目录 1. BIO NIO AIO2. 多线程3. 线程的生命周期和状态4. sleep() ⽅法和 wait() ⽅法对比5. 为什么 wait() ⽅法不定义在 Thread 中&#xff1f; 1. BIO NIO AIO 在Java中&#xff0c;BIO、NIO和AIO是针对网络编程的不同I/O模型&#xff1a; BIO&#xff08;Blocking I/O…

【kotlin】使用MPAndroidChart实现PieChart(饼图)并设置每个数据的颜色、标签等属性

概述 MPAndroidChart 是 Android 上一个非常流行的开源图表库&#xff0c;它提供了多种类型的图表&#xff0c;包括折线图、柱状图、饼图等。 MPAndroidChart 实现饼图 下面是一个使用 MPAndroidChart 实现饼图的示例代码&#xff1a; 首先&#xff0c;需要在项目的 build.…

Makerbase CANable V2.0 产品简介

一、产品介绍 MKS CANable V2.0模块为MKS CANable V1.0升级版本。CANable 2.0是一款小型低成本开源 USB转CAN分析仪。CANable枚举为您计算机上的虚拟串行端口&#xff0c;并充当 CAN总线接口的串行线路。使用candleLight固件时&#xff0c;CANable在Linux上枚举为本地CAN接口。…

MySQL中float、double以及decimal的用法

1、浮点型和定点型 1.1 浮点型&#xff1a; 浮点型能够表示更大的数据范围&#xff0c;但是容易发生精度的问题 float和double属于浮点型&#xff0c;其取值范围与java中的浮点类型的取值范围相同&#xff0c;float占用4字节&#xff0c;double占用8字节 1.2 定点型&#xf…

springboot校园疫情防控管理与数据可视化系统-计算机毕设 附源码84534

springboot校园疫情防控管理与数据可视化系统 摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。针…

实战之如何在VUE中播放RTSP实时推流播放解决方案

一、知识点 常见的直播协议有以下几种 RTMP&#xff08;Real-Time Messaging Protocol&#xff09;实时消息传输协议&#xff1a;是一种用于互联网应用中的协议&#xff0c;最初由 Adobe 公司设计&#xff0c;用于 Flash Player 向 Flash Media Server 或其他支持 RTMP 的服务…

三、Docker命令及基本使用

学习参考&#xff1a;尚硅谷Docker实战教程、Docker官网、其他优秀博客(参考过的在文章最后列出) 目录 前言一、帮助启动类命令1.1 启动docker1.2 停止docker1.3 重启docker1.4 查看docker状态1.5 开机启动1.6 查看docker概要信息1.7 查看docker总体帮助文档1.8 查看docker命令…