@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。滑到最后可以看到配置的规则,如图:
重启Android Studio,让规则生效。 检测到方法大写,不符合命名规范,报导该问题。
类名不符合规范:
从上文可以看到,放在目录下的jar包对所有工程都是有效的。如果要针对单个工程,那么就需要需要AAR形式了。
AAR形式
在同个工程新建一个Android Library,名为lintLibrary,修改相关配置。
1、修改Java工程的依赖
修改自定义lint规则的Java库的build.gradle(这里是上文的Java lib库),注意到要将implementation改为compileOnly。
apply plugin: ‘java-library’
dependencies {
implementation fileTree(dir: ‘libs’, include: [‘*.jar’])
//将implementation改为compileOnly,不然报错
compileOnly ‘com.android.tools.lint:lint-api:26.4.2’
compileOnly ‘com.android.tools.lint:lint-checks:26.4.2’
}
jar {
manifest {
attributes ‘Lint-Registry-v2’: ‘com.gitcode.lib.Register’
}
}
sourceCompatibility = “7”
targetCompatibility = “7”
2、修改Android Library依赖
Android Library主要用来输出AAR文件,要注意到Android Studio新特性的变更(在这里踩了大坑)。
dependencies {
…
lintPublish project(‘:lib’)
}
在Android Studio 3.4+,lintChecks project(':lib')
:lint检查只在当前工程生效,也就是Android Library,并不会打包到AAR文件中。lintPublish project(':lib')
才会将lint检查包含AAR文件中。
3、输出AAR文件
此时跟输出普通的AAR文件没什么区别,但为了手把手教会第一个自定义Issue,我写!
步骤:
菜单栏:View->Tool Windows->Gradle
此时Android Studio在右边会打开如下窗口:
根据上图操作,双击assemble,稍等一会,在控制台看BUILD SUCCESSFUL
,则可在下面目录找到AAR文件。
lintLibrary->build->outputs->aar
这一小节的步骤也可以通过命令行执行。
4、使用AAR文件
有本地依赖或者上传远程仓库,这里只介绍本地依赖。将上小结生成的AAR文件拷贝在app的libs文件夹。并配置app组件的build.gradle
repositories {
flatDir {
dirs ‘libs’
}
}
dependencies {
implementation (name:‘lintlibrary-release’, ext:‘aar’)
}
到这里,就能使用自定义的lint规则了,效果和上面使用jar包是一致的。如果不生效,重启Android Studio看看。
采坑记
1、Found more than one jar in the ‘lintChecks’ configuration. Only one file is supported
这是因为在输出AAR文件中,参考其他人的文章。没有将Java Library的依赖改为compileOnly
。而且Android Library中使用lintChecks
。
2、输出AAR文件没有生效
不知道为什么,Linkedin的参考文章没有生效,可能是Android Studio版本的问题。
另外使用lintChecks输出AAR不生效,Android Studio 3.4+新特性变更,采用lintPublish(AGP 3.4+)。
总结
花了好长好长的时间写本文,差点就放弃了。因为自己Android Studio看不了lint的源码,只能从网上找,网上又找不到最新的doc。过滤太多雷同文章,差点想哭,一些最新的文章也跟不上相关技术的更新。。。
但是一切都值得,因为能帮助到想学习Android Studio lint工具的同学,一起向往美好的生活。
GitHub
点个赞行不
写此文找到的一些具有参考意义的文章:
Android 官方指导
Linkedin 指导
美团->Android自定义Lint实践
lint-custom-rules
另外:本文没有demo,demo的代码已经贴在文章里了。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级安卓工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
79164)]
[外链图片转存中…(img-l88RBGkp-1710933579165)]
[外链图片转存中…(img-7AKu3LFP-1710933579165)]
[外链图片转存中…(img-Zv8RK5P1-1710933579165)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Android)
[外链图片转存中…(img-2unk0syM-1710933579166)]