日志模块封装:单例模式+策略模式+构建者模式+bugly
- 一.单例模式+策略模式+构建者模式
- 二.日志模块封装
- 1.日志等级:LoggerLevel枚举类
- 2.日志输出策略:LoggerStrategy枚举类
- 3.ILogger接口
- 4.LogCatLogger/FileLogger/NetWorkLogger/EmailLogger
- 5.使用构建者模式和策略模式创建对应的logger对象
- 6.最后业务模块中使用:
- 三.bugly的使用
- 1.什么是Bugly
- 2.集成Bugly
- 3.如何创建Bugly产品
- 4.面试问题难点:如果项目混淆后如何准确定位到错误的信息
- 0.现象
- (1)集成文档最后
- (2)点击符号表配置最后
- (3)下载
一.单例模式+策略模式+构建者模式
设计模式传送门
二.日志模块封装
默认情况下我们的日志只能打印输出,没有永久保存,这里我们的日志不仅能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 = trueprivate var TAG = ""private var level = LoggerLevel.Debugprivate 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:ILoggerinit {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.Debugvar loggerType: LoggerStrategy = LoggerStrategy.LOGCATvar isDebug:Boolean = truevar saveUrl:String = "默认路径"fun setTAG(TAG:String):Builder{this.TAG = TAGreturn this}fun setLevel(level:LoggerLevel):Builder{this.level = levelreturn this}fun setLoggerType(loggerType: LoggerStrategy):Builder{//设置策略this.loggerType = loggerTypereturn this}fun isDebug(isDebug: Boolean):Builder{this.isDebug = isDebugreturn this}fun setSaveUrl(saveUrl: String):Builder{this.saveUrl = saveUrlreturn 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。崩溃信息中可以看到报错的具体位置,即使代码混淆后