ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

代码洁癖症的我,学习 Lint 学到心态爆炸,android开发基础课程

2022-01-22 18:31:23  阅读:169  来源: 互联网

标签:Lint 规则 lint 洁癖 Detector android Issue public


<?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来看看代码质量如何吧。

1、通过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相关方法。例如:

@Overridepublic 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输入下面命令:
SSUE);

}

}

在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输入下面命令:

标签:Lint,规则,lint,洁癖,Detector,android,Issue,public
来源: https://blog.csdn.net/m0_66264910/article/details/122641277

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有