日志模块封封装:单例模式+策略模式+构建者模式+bugly

本文介绍了如何使用Kotlin结合单例模式、策略模式和构建者模式来封装日志模块,包括定义日志等级和输出策略,实现不同的日志记录器如LogCatLogger、FileLogger等。此外,还详细讲解了腾讯Bugly的集成及在项目混淆后如何定位错误信息的方法。
摘要由CSDN通过智能技术生成

一.单例模式+策略模式+构建者模式

设计模式传送门

二.日志模块封装

在这里插入图片描述
默认情况下我们的日志只能打印输出,没有永久保存,这里我们的日志不仅能log输出还要能上传到网络,邮件或者本地存储,下面我们进行简单的封装,这里涉及到kotlin基础以及单例模式/策略模式/构建者模式
在这里插入图片描述

1.日志等级:LoggerLevel枚举类

/**
 * @Author : ytx
 * @Time : On 2023/5/21 15:23
 * @Description : LoggerLevel 日志等级
 */
enum class LoggerLevel(var value: Int) {
    Verbose(1),
    Debug(2),
    Info(3),
    Warn(4),
    Error(5)
}

2.日志输出策略:LoggerStrategy枚举类


/**
 * @Author : ytx
 * @Time : On 2023/5/21 15:36
 * @Description : LoggerType 日志输出策略
 */
enum class LoggerStrategy {
    LOGCAT,FILE,EMAIL,NET
}

3.ILogger接口

/**
 * @Author : ytx
 * @Time : On 2023/5/21 15:18
 * @Description : ILogger:所有logger顶层接口
 */
interface ILogger {
    fun d(tag:String,log:String)
    fun v(tag:String,log:String)
    fun i(tag:String,log:String)
    fun w(tag:String,log:String)
    fun e(tag:String,log:String)

    /**
     * 是否Debug
     */
    fun setDebug(isDeug:Boolean)

    /**
     * 默认TAG
     */
    fun setLogTAG(TAG:String)
    /**
     * 默认日志等级
     */
    fun setLoggerLevel(level:LoggerLevel)
    /**
     * Log存储位置,可以是本地路径 可以是网络路径 可以是Email地址
     */
    fun setSaveUrl(url:String)
}

4.LogCatLogger/FileLogger/NetWorkLogger/EmailLogger

创建logger包,下面分别对应4种不同方式,以LogCatLogger为案例

/**
 * @Author : ytx
 * @Time : On 2023/5/21 15:26
 * @Description : LogcatLogger:打印输出log
 */
class LogcatLogger: ILogger {
    private var isDebug = true
    private var TAG = ""
    private var level = LoggerLevel.Debug
    private var loggerFormat = "(:=>$TAG %s -->%s"
    private var url = ""
    override fun d(tag: String, log: String) {
        if(isDebug && level.ordinal >= LoggerLevel.Debug.ordinal){
            Log.d(TAG,String.format(loggerFormat,tag,log))
        }
    }

    override fun v(tag: String, log: String) {
        if(isDebug && level.ordinal >= LoggerLevel.Verbose.ordinal){
            Log.v(TAG,String.format(loggerFormat,tag,log))
        }
    }

    override fun i(tag: String, log: String) {
        if(isDebug && level.ordinal >= LoggerLevel.Info.ordinal){
            Log.i(TAG,String.format(loggerFormat,tag,log))
        }
    }

    override fun w(tag: String, log: String) {
        if(isDebug && level.ordinal >= LoggerLevel.Warn.ordinal){
            Log.w(TAG,String.format(loggerFormat,tag,log))
        }
    }

    override fun e(tag: String, log: String) {
        if(isDebug && level.ordinal >= LoggerLevel.Error.ordinal){
            Log.e(TAG,String.format(loggerFormat,tag,log))
        }
    }

    override fun setDebug(isDebug: Boolean) {
        this.isDebug = isDebug
    }

    override fun setLogTAG(TAG: String) {
       this.TAG = TAG
    }

    override fun setLoggerLevel(level: LoggerLevel) {
        this.level = level
    }

    override fun setSaveUrl(url: String) {
        this.url = url
    }
}

5.使用构建者模式和策略模式创建对应的logger对象

/**
 * @Author : ytx
 * @Time : On 2023/5/21 15:37
 * @Description : Logger创建对应的logger对象 采用策略模式和构建者
 */
class Logger private constructor (private val TAG:String, private val level:LoggerLevel, private val loggerType: LoggerStrategy, private val isDebug:Boolean, private val saveUrl:String) {
    private var logger:ILogger
    init {
        logger = getLogger()
    }
    constructor(builder: Builder):this(
        builder.TAG,
        builder.level,
        builder.loggerType,
        builder.isDebug,
        builder.saveUrl
    )

    /**
     * 创建Logger
     */
    fun getLogger():ILogger{
        when(loggerType){
            LoggerStrategy.EMAIL -> throw IllegalArgumentException("该方案未实现")
            LoggerStrategy.FILE -> throw IllegalArgumentException("该方案未实现")
            LoggerStrategy.NET -> throw IllegalArgumentException("该方案未实现")
            LoggerStrategy.LOGCAT -> logger = LogcatLogger()
        }
        logger.setLoggerLevel(level)
        logger.setLogTAG(TAG)
        logger.setDebug(isDebug)
        logger.setSaveUrl(saveUrl)
        return logger
    }

    /**
     * 输出Debug log
     */
    fun d(Tag:String,log:String){
        logger.d(Tag,log)
    }

    /**
     * 输出Warn log
     */
    fun w(Tag:String,log:String){
        logger.w(Tag,log)
    }

    /**
     * 输出Verbose log
     */
    fun v(Tag:String,log:String){
        logger.v(Tag,log)
    }

    /**
     * 输出Error log
     */
    fun e(Tag:String,log:String){
        logger.e(Tag,log)
    }
    /**
     * 输出Info log
     */
    fun i(Tag:String,log:String){
        logger.i(Tag,log)
    }



    class Builder{
        var TAG:String = "默认TAG"
        var level:LoggerLevel = LoggerLevel.Debug
        var loggerType: LoggerStrategy = LoggerStrategy.LOGCAT
        var isDebug:Boolean = true
        var saveUrl:String = "默认路径"

        fun setTAG(TAG:String):Builder{
                this.TAG = TAG
                return this
            }
            fun setLevel(level:LoggerLevel):Builder{
                this.level = level
                return this
            }

            fun setLoggerType(loggerType: LoggerStrategy):Builder{//设置策略
                this.loggerType = loggerType
                return this
            }

            fun isDebug(isDebug: Boolean):Builder{
                this.isDebug = isDebug
                return this
            }


            fun setSaveUrl(saveUrl: String):Builder{
                this.saveUrl = saveUrl
                return this
            }

            fun build():Logger{
                return Logger(this)
            }
        }



}

6.最后业务模块中使用:

class LoggerUtils {
    companion object{
        private val logger = Logger.Builder()
            .setLevel(LoggerLevel.Error)
            .setLoggerType(LoggerStrategy.LOGCAT)
            .isDebug(true)
            .setTAG("main业务模块")
            .build()

        fun d(tag:String,log:String){
            logger.d(tag,log)
        }
    }
}
LoggerUtils.d("123","234")

三.bugly的使用

1.什么是Bugly

腾讯Bugly,为移动开发者提供专业的异常上报和运营统计,帮助开发者快速发现并
解决异常,同时掌握产品运营动态,及时跟进用户反馈。

2.集成Bugly

https://bugly.qq.com/docs/user-guide/instruction-manual-android/?v=1.0.0

3.如何创建Bugly产品

https://bugly.qq.com/v2/workbench/apps

在这里插入图片描述

4.面试问题难点:如果项目混淆后如何准确定位到错误的信息

0.现象

class Utils {
    companion object{
        fun chu2( num1:Int, num2:Int):Int{
            return num1/num2
        }
    }
}
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        //制造异常
        var result = Utils.chu2(4,0)
    }
}

设置代码混淆在这里插入图片描述
打包成apk,并将apk安装到手机上,报错,不显示Utils的第几行报错,因为Utils默认被混淆,而activity安卓的四大组件默认不被混淆,那么怎么解决这个问题呢
在这里插入图片描述

解决问题方案:

(1)集成文档最后

在这里插入图片描述

(2)点击符号表配置最后

在这里插入图片描述

(3)下载

在这里插入图片描述
a。将jar扔到根目录下,注意根目录不是libs
b。大家可以看文档的有关参数说明,我这边使用的命令是这样,以后可以方便复制使用
java -jar buglyqq-upload-symbol.jar -appid xxxx -appkey xxxxx -bundleid com.zhongjh -version 5.5.0 -platform Android -inputSymbol D:\XXX\build\outputs\mapping\debug\mapping.txt -inputMapping D:\XXX\build\outputs\mapping\debug\mapping.txt
然后回车,执行,看到200则表示上传成功
在这里插入图片描述
c。崩溃信息中可以看到报错的具体位置,即使代码混淆后
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值