布景
在开发过程中,调试是必不可少的一项工作。
当咱们要确认项目的逻辑时,当咱们要了解界面的生命周期时,当咱们发现新写的逻辑与期望作用不一致时,当咱们觉得数据有问题时……
而调试有两种办法:
第一种便是运用debug模式运转APP,然后经过断点让程序运转到指定方位进行分析。
第二种便是打日志的办法,经过观察输出来确认程序是否运转到该方位以及此刻的数据。
本篇文章首要聚集在第二种办法上面。
在Android里边,打日志运用的体系API是Log,你以为直接运用就完了吗?
封装
假定你在需求打印日志的当地直接运用体系的API,那么当遇到下面状况时,会「牵一发而动全身」。
场景一:假如我打印日志要用三方库的日志API,那么我要查找项目一切运用方位,并一一替换。
场景二:假如我期望在开发环境下打印日志,release环境不打印,这个时候每个方位都需求单独做处理。
因而咱们需求在运用Log进行日志打印之前,做一层封装。
假定咱们的类姓名为ZLog,代码如下:
importandroid.util.Log;/**
*Createdon2019-10-26
*
*@authorZengyu.Zhan
*/publicclassZLog{publicstaticintv(Stringtag,Stringmsg){returnLog.v(tag,msg);
}publicstaticintd(Stringtag,Stringmsg){returnLog.d(tag,msg);
}publicstaticinti(Stringtag,Stringmsg){returnLog.i(tag,msg);
}publicstaticintw(Stringtag,Stringmsg){returnLog.w(tag,msg);
}publicstaticinte(Stringtag,Stringmsg){returnLog.e(tag,msg);
}
}
这样处理之后,关于场景一和场景二,咱们需求修改的仅仅ZLog这个类,而不需求到详细运用ZLog的一切当地去修改。
供给日志打印操控
咱们知道,日志打印或许包含灵敏信息,并且过多的日志打印或许影响APP的功能,因而咱们一般是在开发时候打开日志,在发布APP之前关闭。
因而咱们这边需求供给一个标志位来操控日志的打印与否。
importandroid.util.Log;/**
*Createdon2019-10-26
*
*@authorZengyu.Zhan
*/publicclassZLog{privatestaticbooleanisDebugMode=false;publicstaticvoidsetDebugMode(booleandebugMode){
isDebugMode=debugMode;
}publicstaticintv(Stringtag,Stringmsg){returnisDebugMode?Log.v(tag,msg):-1;
}publicstaticintd(Stringtag,Stringmsg){returnisDebugMode?Log.d(tag,msg):-1;
}publicstaticinti(Stringtag,Stringmsg){returnisDebugMode?Log.i(tag,msg):-1;
}publicstaticintw(Stringtag,Stringmsg){returnisDebugMode?Log.w(tag,msg):-1;
}publicstaticinte(Stringtag,Stringmsg){returnisDebugMode?Log.e(tag,msg):-1;
}
}
默许是不开启日志打印,防止开发者忘掉设置。
一般日志和奔溃栈体系日志在操控台的输出比照
现在咱们在APP里边运用ZLog打印日志,代码为:
ZLog.setDebugMode(true);
ZLog.e(“ZLog”,”justtest”);
输出如下:
咱们现在增加如下代码:
StringnullString=null;if(nullString.equals(“null”)){
}
运转之后操控台会显现空指针反常奔溃栈,如下:
能够看到奔溃栈信息会显现详细是哪个文件呈现了空指针,以及详细哪一行。在咱们这个比如里边便是MainActivity.java的24行。
并且点击蓝色链接光标会直接定位到错误方位。
假如咱们一般的日志也能够点击就跳转到对应方位,关于咱们开发来说效率是有很大提高的。
ZLogHelper
已然奔溃栈里边有链接能够跳转,那么咱们能够经过栈信息来获取日志的打印方位。
咱们直接上代码:
publicclassZLogHelper{privatestaticfinalintCALL_STACK_INDEX=1;privatestaticfinalPatternANONYMOUS_CLASS=Pattern.compile(“(\$\d+)+$”);publicstaticStringwrapMessage(intstackIndex,Stringmessage){//DONOTswitchthistoThread.getCurrentThread().getStackTrace().if(stackIndex<0){
stackIndex=CALL_STACK_INDEX;
}
StackTraceElement[]stackTrace=newThrowable().getStackTrace();if(stackTrace.length<=stackIndex){thrownewIllegalStateException(“Syntheticstacktracedidn’thaveenoughelements:areyouusingproguard?”);
}
Stringclazz=extractClassName(stackTrace[stackIndex]);intlineNumber=stackTrace[stackIndex].getLineNumber();
message=”.(“+clazz+”.java:”+lineNumber+”)-“+message;returnmessage;
}/**
*Extracttheclassnamewithoutanyanonymousclasssuffixes(e.g.,{@codeFoo$1}
*becomes{@codeFoo}).
*/privatestaticStringextractClassName(StackTraceElementelement){
Stringtag=element.getClassName();
Matcherm=ANONYMOUS_CLASS.matcher(tag);if(m.find()){
tag=m.replaceAll(“”);
}returntag.substring(tag.lastIndexOf(‘.’)+1);
}
}
这儿咱们对外供给一个wrapMessage办法,看姓名就知道是对Message进行包装。
办法里边也是对StackTraceElement进行分析。
这边还做了一个操控,防止stackIndex呈现负数状况。
或许有小伙伴会好奇,为什么要把stackIndex对外开放呢?
因为你打印日志的当地不相同,这儿的stackIndex也需求对应调整。
办法里边是对StackTraceElement做处理,而StackTraceElement跟你的办法层级有联系。
咱们以最常用的两种日志打印方式为例,来阐明这儿的stackIndex要怎样传递,以及这个ZLogHelper的用法。
直接代码运用
咱们在MainActivity.java中直接运用,stackIndex传入1即可。
Log.e(“ZLog”,ZLogHelper.wrapMessage(1,”justtest”));
操控台输出如下:
能够看到代码地点的类和行数到显现为链接文本,点击会定位到详细的方位。
做了封装的状况
一般咱们对Log都会做封装,因而假定咱们有一个LogUtils类,咱们在MainActivity.java里边调用。
LogUtils.java:
classLogUtils{publicstaticvoidloge(){
Log.e(“ZLog”,ZLogHelper.wrapMessage(2,”justtest”));
}
}
MainActivity.java:
LogUtils.loge();
咱们先看下结果,再来分析。操控台输出如下:
能够看到的确定位到了MainActivity.java中的详细运用当地。
那么为什么这儿传入的stackIndex跟第一种不相同,是2而不是1呢?
其实答案很简单,你改为1之后,输出的操控台显现的会定位到LogUtils里边的日志打印句子处。在这儿便是:
Log.e(“ZLog”,ZLogHelper.wrapMessage(2,”justtest”));
所以其实你能够看出一个规则,而这个从代码也能够发现。
因为代码里边解析调用方位是根据栈来的,对StackTraceElement进行分析,因而状况一直接运用,传入1。而状况二多了一层函数调用,经过loge办法做了一层包装。因而需求传入2。假如你再套一层,那么需求传入3。了解了这一点,咱们下面的东西类信任你就看得懂了。
ZLog
假如你不想自己手动传入stackIndex,能够直接运用咱们供给的东西类ZLog。
publicclassZLog{privatestaticbooleanisDebugMode=false;publicstaticvoidsetDebugMode(booleandebugMode){
isDebugMode=debugMode;
}privatestaticbooleanisLinkMode=true;publicstaticvoidsetLinkMode(booleanlinkMode){
isLinkMode=linkMode;
}privatestaticfinalintCALL_STACK_INDEX=3;publicstaticintv(Stringtag,Stringmsg){returnisDebugMode?Log.v(tag,mapMsg(msg)):-1;
}publicstaticintd(Stringtag,Stringmsg){returnisDebugMode?Log.d(tag,mapMsg(msg)):-1;
}publicstaticinti(Stringtag,Stringmsg){returnisDebugMode?Log.i(tag,mapMsg(msg)):-1;
}publicstaticintw(Stringtag,Stringmsg){returnisDebugMode?Log.w(tag,mapMsg(msg)):-1;
}publicstaticinte(Stringtag,Stringmsg){returnisDebugMode?Log.e(tag,mapMsg(msg)):-1;
}privatestaticStringmapMsg(Stringmsg){returnisLinkMode?ZLogHelper.wrapMessage(CALL_STACK_INDEX,msg):msg;
}
}
信任有了前面的常识,小伙伴关于这儿为什么传入3应该了解了。
1的话会定位到
returnisLinkMode?ZLogHelper.wrapMessage(CALL_STACK_INDEX,msg):msg;
2的话(以e为例)会定位到
returnisDebugMode?Log.e(tag,mapMsg(msg)):-1;
3的话才能够定位到外面详细的调用途。
优化
咱们知道,虽然ZLog做了封装,但是咱们每次打日志都要传入ZLog,有点麻烦?
能否供给一个默许的TAG,允许对外设置。
能够的,咱们修改如下(以e为例):
privatestaticStringtag=”ZLOG”;publicstaticvoidsetTag(Stringtag){if(!TextUtils.isEmpty(tag)){
ZLog.tag=tag;
}
}publicstaticinte(Stringtag,Stringmsg){returnisDebugMode?Log.e(mapTag(tag),mapMsg(msg)):-1;
}publicstaticinte(Stringmsg){returnisDebugMode?Log.e(tag,mapMsg(msg)):-1;
}privatestaticStringmapTag(Stringtag){returnTextUtils.isEmpty(tag)?ZLog.tag:tag;
}
项目实战
按照下面两步引入开源库。
Step1.AddtheJitPackrepositorytoyourbuildfile
Additinyourrootbuild.gradleattheendofrepositories:
allprojects{
repositories{
…
maven{url’https://jitpack.io’}
}
}
Step2.Addthedependency
dependencies{
implementation’com.github.nesger:AndroidWheel:1.0.0′}
运用时先打开开关:
ZLog.setDebugMode(true);
然后就能够直接运用了。
温馨提示
由于带链接的debug对功能有必定影响,因而建议开发运用,上线关闭。
结语
这边在完善一个开源仓库AndroidWheel,跟姓名相同,防止重复造轮子。
现在1.0.0版本供给日志相关东西类,1.0.1增加了防抖动EditText。
后续会持续更新迭代,功能会更完善更全面。
觉得不错,欢迎给个star哈~
1、IT大王遵守相关法律法规,由于本站资源全部来源于网络程序/投稿,故资源量太大无法一一准确核实资源侵权的真实性;
2、出于传递信息之目的,故IT大王可能会误刊发损害或影响您的合法权益,请您积极与我们联系处理(所有内容不代表本站观点与立场);
3、因时间、精力有限,我们无法一一核实每一条消息的真实性,但我们会在发布之前尽最大努力来核实这些信息;
4、无论出于何种目的要求本站删除内容,您均需要提供根据国家版权局发布的示范格式
《要求删除或断开链接侵权网络内容的通知》:https://itdw.cn/ziliao/sfgs.pdf,
国家知识产权局《要求删除或断开链接侵权网络内容的通知》填写说明: http://www.ncac.gov.cn/chinacopyright/contents/12227/342400.shtml
未按照国家知识产权局格式通知一律不予处理;请按照此通知格式填写发至本站的邮箱 wl6@163.com