tools:ignore=“UnusedResources” >
父容器声明了ignore属性,那么子视图会继承该属性。例如上文LinearLayout中声明了禁止Lint检查LinearLayout的UnusedResources问题,TextView自然也禁止检查该问题。禁止检查多个问题,问题之间用逗号隔开;禁止检查所有问题则使用all
关键字。
tools:ignore=“all”
我们也可以通过配置项目的Gradle文件来禁止检查。
例如禁止Lint检查项目AndroidManifest.xml文件的GoogleAppIndexingWarning问题。在项目对应组件工程的Gradle文件添加如下配置,这样就不会有黄色提醒了。
defaultConfig{
lintOptions {
disable ‘GoogleAppIndexingWarning’
}
}
那么,可以禁止lint工具检查什么问题?
配置Lint
在上文中通过注解和在xml使用属性来禁止Lint工具检查相关问题,其实已经是对Lint的配置了。Lint将多个问题归为一个issue(规则),例如下图右边的的六大规则。
上图是Lint工具的工作流程,下面了解相关概念。 App Source Files 源文件包含组成 Android 项目的文件,包括 Java 和 XML 文件、图标和 ProGuard 配置文件等。 lint.xml 文件 此配置文件可用于指定您希望排除的任何 Lint 检查以及自定义问题严重级别。 lint Tool 我们可以通过Android Studio 对 Android 项目运行此静态代码扫描工具。也可以手动运行。Lint 工具检查可能影响 Android 应用质量和性能的代码结构问题。 Lint 检查结果 我们可以在控制台(命令行运行)或 Android Studio 的 Inspection Results 窗口中查看 Lint 检查结果。
通过Lint工具的工作流程了解到,可以在lint.xml文件配置一些信息。一般新建项目都是没有lint.xml文件的,在项目的根目录创建lint.xml文件。格式如下:
<?xml version="1.0" encoding="UTF-8"?>那么有哪些Issues(规则)呢?
在Android主要有如下六大类:
- Security 安全性。在AndroidManifest.xml中没有配置相关权限等。
- Usability 易用性。重复图标;上文开始黄色警告也属于该规则等。
- Performance 性能。内存泄漏,xml结构冗余等。
- Correctness 正确性。超版本调用API,设置不正确的属性值等。
- Accessibility 无障碍。单词拼写错误等。
- Internationalization国际化。字符串缺少翻译等。
其他更多Issues,可以通将命令行切换到…/Android/sdk/tools/bin目录下,然后输入lint --list
。例如在Mac下: cd /Users/gitcode8/Library/Android/sdk/tools/bin
输入./lint --list
结果如下:
例如官网提供的参考例子:
<?xml version="1.0" encoding="UTF-8"?>学习Lint工具仅仅是为了安抚我的强迫症?不,还不知道Lint真正用来干嘛呢?
检查项目质量
不好容易开发了个APP,准备开始上班摸鱼了。还让代码自查?那就通过Lint来看看代码质量如何吧。
- 通过Android Studio 的菜单栏Analyze选项下拉选择第一个选项Inspect Code.
2、在弹出框根据自己需要选择lint工具的检查范围,这里选择整个项目。检查时间也是根据项目大小来定的。
3、等待一段时间后,会列出检查结果。从下图看到,不仅会检查Android存在的问题,也会检查Java等其他问题。通过单击问题,可以从右边提示框看到问题发生的地方和相关建议。
到这里,就开始对项目修修补补吧。
自定义规则
为什么要自定义呢?已有规则不符合自己或团队开发需求,或者觉得Lint存在一些缺陷。在网上大多数文章千篇一律,都是通过将Log打印来举例,看着都好累哦。由于没有相关官方文档和第三方教程(可能由于lint的api更新太快,没人愿意做这种吃力不讨好的工作),也这就只有这样了。本文通过自定义命名规范规则来讲解整个过程。
Lint中重点的API
先学习相关api,可以快速理解一些概念,可以粗略看过,下结实践再回来看。
1、Issue
Issue如上文所说,表示lint 工具检查的一个规则,一个规则包含若干问题。常在Detector中创建。下文是创建一个Issue的例子。
private static final Issue ISSUE = Issue.create(“NamingConventionWarning”,
“命名规范错误”,
“使用驼峰命名法,方法命名开头小写,类大写字母开头”,
Category.USABILITY,
5,
Severity.WARNING,
new Implementation(NamingConventionDetecor.class,
EnumSet.of(Scope.JAVA_FILE)));
- 第一个参数id 唯一的id,简要表面当前提示的问题。
- 第二个参数briefDescription 简单描述当前问题
- 第三个参数explanation 详细解释当前问题和修复建议
- 第四个参数category 问题类别,例如上文讲到的Security、Usability等等。
- 第五个参数priority 优先级,从1到10,10最重要
- 第六个参数Severity 严重程度:FATAL(奔溃), ERROR(错误), WARNING(警告),INFORMATIONAL(信息性),IGNORE(可忽略)
- 第七个参数Implementation Issue和哪个Detector绑定,以及声明检查的范围。Scope有如下选择范围: RESOURCE_FILE(资源文件),BINARY_RESOURCE_FILE(二进制资源文件),RESOURCE_FOLDER(资源文件夹),ALL_RESOURCE_FILES(所有资源文件),JAVA_FILE(Java文件), ALL_JAVA_FILES(所有Java文件),CLASS_FILE(class文件), ALL_CLASS_FILES(所有class文件),MANIFEST(配置清单文件), PROGUARD_FILE(混淆文件),JAVA_LIBRARIES(Java库), GRADLE_FILE(Gradle文件),PROPERTY_FILE(属性文件),TEST_SOURCES(测试资源),OTHER(其他);
这样就能很清楚的定义一个规则,上文只定义了检查命名规范的规则。
2、IssueRegistry
用于注册要检查的Issue(规则),只有注册了Issue,该Issue才能被使用。例如注册上文的命名规范规则。
public class Register extends IssueRegistry {
@NotNull
@Override
public List getIssues() {
return Arrays.asList(NamingConventionDetector.ISSUE);
}
}
4、Detector
查找指定的Issue,一个Issue对应一个Detector。自定义Lint 规则的过程也就是重写Detector类相关方法的过程。具体看下小结实践。
5、Scanner
扫描并发现代码中的Issue,Detector需要实现Scaner,可以继承一个到多个。
- UastScanner 扫描Java文件和Kotlin文件
- ClassScanner 扫描Class文件
- XmlScanner 扫描Xml文件
- ResourceFolderScanner 扫描资源文件夹
- BinaryResourceScanner 扫描二进制资源文件
- OtherFileScanner 扫描其他文件
- GradleScanner 扫描Gradle脚本
旧版本的JavaScanner、JavaPsiScanner随着版本的更新已经被UastScanner替代了。
自定义Lint规则实践
通过实现命名规范Issue来熟悉和运用上小节相关的api。自定义规则需要在Java工程中创建,这里通过Android Studio来创建一个Java Library。
步骤:File->New->New Mudle->Java Library
这里Library Name为lib。
定义类NamingConventionDetector,并继承自Detector。因为这里是检测Java文件类名和方法是否符合规则,所以实现Detector.UastScanner接口。
public class NamingConventionDetector
extends Detector
implements Detector.UastScanner {
}
在NamingConventionDetector类内定义上文的Issue:
public class NamingConventionDetector
extends Detector
implements Detector.UastScanner {
public static final Issue ISSUE = Issue.create(“NamingConventionWarning”,
“命名规范错误”,
“使用驼峰命名法,方法命名开头小写”,
Category.USABILITY,
5,
Severity.WARNING,
new Implementation(NamingConventionDetector.class,
EnumSet.of(Scope.JAVA_FILE)));
}
重写Detector的createUastHandler方法,实现我们自己的处理类。
public class NamingConventionDetector extends Detector implements Detector.UastScanner {
//定义命名规范规则
public static final Issue ISSUE = Issue.create(“NamingConventionWarning”,
“命名规范错误”,
“使用驼峰命名法,方法命名开头小写”,
Category.USABILITY,
5,
Severity.WARNING,
new Implementation(NamingConventionDetector.class,
EnumSet.of(Scope.JAVA_FILE)));
//返回我们所有感兴趣的类,即返回的类都被会检查
@Nullable
@Override
public List<Class<? extends UElement>> getApplicableUastTypes() {
return Collections.<Class<? extends UElement>>singletonList(UClass.class);
}
//重写该方法,创建自己的处理器
@Nullable
@Override
public UElementHandler createUastHandler(@NotNull final JavaContext context) {
return new UElementHandler() {
@Override
public void visitClass(@NotNull UClass node) {
node.accept(new NamingConventionVisitor(context, node));
}
};
}
//定义一个继承自AbstractUastVisitor的访问器,用来处理感兴趣的问题
public static class NamingConventionVisitor extends AbstractUastVisitor {
JavaContext context;
UClass uClass;
public NamingConventionVisitor(JavaContext context, UClass uClass) {
this.context = context;
this.uClass = uClass;
}
@Override
public boolean visitClass(@org.jetbrains.annotations.NotNull UClass node) {
//获取当前类名
char beginChar = node.getName().charAt(0);
int code = beginChar;
//如果类名不是大写字母,则触碰Issue,lint工具提示问题
if (97 < code && code < 122) {
context.report(ISSUE,context.getNameLocation(node),
“the name of class must start with uppercase:” + node.getName());
//返回true表示触碰规则,lint提示该问题;false则不触碰
return true;
}
return super.visitClass(node);
}
@Override
public boolean visitMethod(@NotNull UMethod node) {
//当前方法不是构造方法
if (!node.isConstructor()) {
char beginChar = node.getName().charAt(0);
int code = beginChar;
//当前方法首字母是大写字母,则报Issue
if (65 < code && code < 90) {
context.report(ISSUE, context.getLocation(node),
“the method must start with lowercase:” + node.getName());
//返回true表示触碰规则,lint提示该问题;false则不触碰
return true;
}
}
return super.visitMethod(node);
}
}
}
上文NamingConventionDetector类,已经是全部代码,只检查类名和方法名是否符合驼峰命名法,可以根据具体需求,重写抽象类AbstractUastVisitor的visitXXX方法。
如果处理特定的方法或者其他,也可以使用默认的处理器。重写Scanner相关方法。例如:
@Override
public List getApplicableMethodNames() {
return Arrays.asList(“e”,“v”);
}
表示e(),v()方法会被检测到,并调用visitMethod()方法,实现自己的逻辑。
@Override
public void visitMethod JavaContext context, JavaElementVisitor visitor, PsiMethodCallExpression call, PsiMethod method) {
//todo something
super.visitMethod(context, visitor, call, method);
}
接下来就是注册自定义的Issue:
public class Register extends IssueRegistry {
@NotNull
@Override
public List getIssues() {
return Arrays.asList(NamingConventionDetector.ISSUE);
}
}
在lib项目的build.gradle文件添加相关代码:
apply plugin: ‘java-library’
dependencies {
implementation fileTree(dir: ‘libs’, include: [‘*.jar’])
implementation ‘com.android.tools.lint:lint-api:26.4.2’
implementation ‘com.android.tools.lint:lint-checks:26.4.2’
}
//添加如下代码
jar {
manifest {
attributes ‘Lint-Registry’: ‘com.gitcode.lib.Register’
}
}
sourceCompatibility = “7”
targetCompatibility = “7”
到这里就自定义Lint自定义规则就搞定了,接着是使用和确定规则是否正确。
使用自定Lint规则
使用自定义Lint规则有两种形式:jar包和AAR文件。
jar形式使用
在Android Studio的Terminal输入下面命令:
./gradlew lib:assemble
看到BUILD SUCCESSFUL
则表示生成jar包成功,可以在下面路径找到:
lib->build->libs
如图:
将lib.jar拷贝下面目录:
~/.android/lint/
如果lint文件夹不存在,则创建。通过命令行输入lint --list。滑到最后可以看到配置的规则,如图:
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
-1715843180667)]
[外链图片转存中…(img-QCKBQxRA-1715843180668)]
[外链图片转存中…(img-jrpJii45-1715843180669)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!