什么是Android Lint,它如何帮助您编写支持的代码

什么是Android Lint,它如何帮助您编写支持的代码


如果开发人员不够谨慎,事情可能会变得很糟糕。 例如,经典的开发人员遗漏是使用与旧代码不兼容的API新版本,执行需要特殊用户权限的操作,以及应用程序本地化方面的空白。 这些只是其中的一些。


此外,Java和Kotlin与其他任何编程语言一样,都有自己的构造,这些构造可能导致性能下降。


你好皮棉


我们使用称为Lint(或Linter)的工具来避免此类问题。 Lint是静态代码分析工具,可帮助开发人员在代码编译之前发现潜在问题。 Lint对源代码执行多次检查,可以检查诸如未使用的变量或函数参数,条件简化,范围错误,变量或函数未定义,代码优化不佳等问题。 当我们谈论Android开发时,有数百个Lint可用


但是有时我们需要在代码中找到这些现有检查未涵盖的特定问题。


您好自定义检查Lint


在开始编码之前,让我们定义目标,并了解如何使用Lint API逐步实现它。 目的是创建检查以检测对象的错误方法调用。 该测试的目的是确定在View组件上安装侦听器的方法是否会中断对该组件的几次连续单击,以便我们避免多次打开同一Activity或访问网络。


Lint用户检查是作为标准Java(或Kotlin)模块的一部分编写的。 最简单的入门方法是创建一个简单的基于Gradle的项目(不一定是Android项目)。


然后添加Lint依赖项。 在模块的build.gradle文件中添加:


 compileOnly "com.android.tools.lint:lint-api:$lintVersion" compileOnly "com.android.tools.lint:lint-checks:$lintVersion" 

现在,在研究此主题时,我学到了一个技巧。 lintVersion应该是gradlePluginVersion + 23.0.0gradlePluginVersion是在项目级别的build.gradle文件中定义的变量。 目前,最新的稳定版本是3.3.0。 这意味着lintVersion应该为26.3.0。


每张Lint支票包含4个部分:


  • 问题是我们试图防止的代码问题。 当Lint检查失败时,这将报告给开发人员。
  • 检测器是提供Lint API的问题发现工具。
  • 实现是可能出现问题的区域(源文件,XML文件,编译的代码等)。
  • 注册表是自定义的Lint检查注册表,它将与包含预定义检查的现有注册表一起使用。

实作


让我们开始为自定义验证创建一个实现。 每个实现都包含一个实现检测器和范围的类。


 val correctClickListenerImplementation = Implementation(CorrectClickListenerDetector::class.java, Scope.JAVA_FILE_SCOPE) 

请记住, Scope.JAVA_FILE_SCOPE也适用于Kotlin类。


问题


下一步是使用此实现来确定问题。 每个问题都包含以下几个部分:


  • ID是唯一标识符。
  • 说明 -问题的简短说明 (5-6个字)。
  • 说明对问题的完整说明,并提供有关解决方法的建议。
  • 类别 -问题的类别(性能,翻译,安全性等)。
  • 优先级 -问题的重要性,范围为1到10,其中10为最高。 这将用于在启动Lint时创建的报告中对问题进行排序。
  • 严重性-问题的严重性(严重,错误,警告,信息或忽略)。
  • 一个实现是将用于检测此问题的实现。

 val ISSUE_CLICK_LISTENER = Issue.create( id = "UnsafeClickListener", briefDescription = "Unsafe click listener", explanation = """" This check ensures you call click listener that is throttled instead of a normal one which does not prevent double clicks. """.trimIndent(), category = Category.CORRECTNESS, priority = 6, severity = Severity.WARNING, implementation = correctClickListenerImplementation ) 

检测器


Lint API为您可以在实现中定义的每个区域提供接口。 这些接口中的每一个都提供了一些方法,您可以覆盖和访问您感兴趣的代码部分。


  • UastScanner -Java或Kotlin文件(UAST- 统一抽象语法树 (俄语统一抽象语法树 ))。
  • ClassScanner-编译文件(字节码)。
  • BinaryResourceScanner-二进制资源,例如位图或res/raw文件。
  • ResourceFolderScanner-资源文件夹(不是其中的特定文件)。
  • XmlScanner -XML文件。
  • GradleScanner -Gradle文件。
  • OtherFileScanner-其他所有内容。

另外, Detector类是一个基类,具有上述每个接口提供的所有方法的空实现,因此,如果只需要一个方法,则无需实现完整接口。


现在,我们准备实现一个检测器,它将检查对象的正确方法调用。


 private const val REPORT_MESSAGE = "Use setThrottlingClickListener" /** *   ,        *     ,      . */ class CorrectClickListenerDetector : Detector(), Detector.UastScanner { /** * ,  ,      . *         , *          , *      ,   . */ override fun getApplicableUastTypes(): List<Class<out UElement>>? { return listOf<Class<out UElement>>(UCallExpression::class.java) } /** *      UAST,    , *    UAST   .    UElementHandler, *   ,     , *    ,  , , ,   .. *        ,    *    .     —  ,   *   ,    ,       . */ override fun createUastHandler(context: JavaContext): UElementHandler? { return object: UElementHandler() { override fun visitCallExpression(node: UCallExpression) { if (node.methodName != null && node.methodName?.equals("setOnClickListener", ignoreCase = true) == true) { context.report(ISSUE_CLICK_LISTENER, node, context.getLocation(node), REPORT_MESSAGE, createFix()) } } } } /** *    ,    *   IDE,      . */ private fun createFix(): LintFix { return fix().replace().text("setOnClickListener").with("setThrottlingClickListener").build() } } 

注册表


我们需要做的最后一件事是在注册表中添加问题,并告诉Lint它应该与标准注册表一起使用特殊的问题注册表。


 class MyIssueRegistry : IssueRegistry() { override val issues: List<Issue> = listOf(ISSUE_CLICK_LISTENER) } 

build.gradle模块级别:


 jar { manifest { attributes("Lint-Registry-v2": "co.infinum.lint.MyIssueRegistry") } } 

其中co.infinum.lintMyIssueRegistry类的包。 现在,您可以使用gradlew脚本运行jar任务,该库应出现在build/libs目录中。


是Lint用户检查的另一个示例,您可以在其中查看如何处理XML文件。


使用方法


新的Lint支票已准备就绪,可以在项目中使用。 如果此检查可以应用于所有项目,则可以将其放在~/.android/lint文件夹中(如果尚不存在,则可以创建它)。


另外,您可以将检查放在项目中的单独模块中,并使用lintChecks方法像其他任何依赖项一样启用此模块。


值得吗?


Lint是每个开发人员都应该使用的非常好的工具。 能够及早发现代码中的潜在问题非常有帮助。 尽管自定义检查不容易编写,主要是由于API的复杂性,但绝对值得,并且可以在将来节省大量时间和精力。

Source: https://habr.com/ru/post/zh-CN456272/


All Articles