Android代码检查规则Lint的自定义与应用详解

目录
  • 前言:
  • 什么是Lint
  • 自定义Lint流程:
    • 1. 新创建module,Module类型选择Java or Kotlin Library, 暂时命名lint_tools
    • 2. 在build.gradle中引入lint的依赖
    • 3. 本地创建个资源id命名检查规则,用来规范项目中的id统一命名
    • 4. 实现IssueRegistry并添加对应的自定义Issue:
    • 5. 在module(lint_tools)中对应的build.gradle中配置如下信息:
    • 6. 在需要进行lint检查的module中或者app目录现的build.gradle中引用对应的lint_tools即可使用。
  • 拓展一下:
    • 1. 针对Issue.create参数了解一下:

前言:

在日常的代码开发中,此处相信每个开发人员对代码质量都是高要求,有自己的一套代码规范,但是我们不是单独作战,往往大家都是团队作战,人是最大的变量,各人各异,如何保证团队的代码质量和代码规范呢?靠开发者自觉吗?也许有的团队有严格的CR机制,在MR阶段会进行CR,CR不通过的MR是不允许合入的,但是这样会使Reviewer花费较多的时间去校验,那么这时候我们就需要在编码过程中提供一种代码检测机制。

例如:期望表现的效果就是在编码时可以展示异常检测的方法,高亮或者标红,当鼠标悬停在高亮的代码上时,会提供问题的描述和解决方法。需要这种效果,就需要自定义lint了。

什么是Lint

在Android Studio中提供的代码扫描工具Lint,可在无需实际执行该应用,也不必编写测试用例的情况下帮助开发者发现代码质量问题和提出一些改进建议。

Lint工具可检查您的 Android 项目源文件是否包含潜在错误,以及在正确性、安全性、性能、易用性、便利性和国际化方面是否需要优化改进。在使用 Android Studio 时,配置的 Lint 和 IDE 检查会在您每次构建应用时运行。不过,您可以手动运行检查或从命令行运行 Lint。

android studio内置了较多的lint规则,但内置的lint规则无法满足直观的适合我们时,就需要我们自定义lint了。

自定义Lint流程:

1. 新创建module,Module类型选择Java or Kotlin Library, 暂时命名lint_tools

2. 在build.gradle中引入lint的依赖

    dependencies {
        compileOnly 'com.android.tools.lint:lint-api:27.2.2'
        compileOnly 'com.android.tools.lint:lint-checks:27.2.2'
    }

在moudle中依赖了lint-api和lint-checks,其中lint-api就是lint相关的api,lint-checks就是android studio里自定义的一些lint规则,我们自定义lint可以参考lint-checks里面的写法。

3. 本地创建个资源id命名检查规则,用来规范项目中的id统一命名

创建ViewIdDetector,直接继承LayoutDetector(也可以继承ResourceXmlDetector 或者 继承Detector实现的接口是XmlScanner,方式多样)

import com.android.SdkConstants
import com.android.tools.lint.detector.api.*
import com.android.tools.lint.detector.api.Category.Companion.CORRECTNESS
import com.android.tools.lint.detector.api.Scope.Companion.RESOURCE_FILE_SCOPE
import org.w3c.dom.Element
​
class ViewIdDetector : LayoutDetector() {

    override fun getApplicableElements(): Collection<String>? {
        return listOf(
            SdkConstants.TEXT_VIEW,
            SdkConstants.IMAGE_VIEW,
            SdkConstants.BUTTON
        )
    }
​
    override fun visitElement(context: XmlContext, element: Element) {
        if (!element.hasAttributeNS(SdkConstants.ANDROID_URI, SdkConstants.ATTR_ID)) {
            return
        }
        val attr = element.getAttributeNodeNS(SdkConstants.ANDROID_URI, SdkConstants.ATTR_ID)
        val value = attr.value
        if (value.startsWith(SdkConstants.NEW_ID_PREFIX)) {
            val idValue = value.substring(SdkConstants.NEW_ID_PREFIX.length)
            var matchRule = true
            var expMsg = ""
            when (element.tagName) {
                SdkConstants.TEXT_VIEW -> {
                    expMsg = "tv"
                    matchRule = idValue.startsWith(expMsg)
                }
                SdkConstants.IMAGE_VIEW -> {
                    expMsg = "iv"
                    matchRule = idValue.startsWith(expMsg)
                }
                SdkConstants.BUTTON -> {
                    expMsg = "btn"
                    matchRule = idValue.startsWith(expMsg)
                }
            }
            if (!matchRule) {
                context.report(
                    ISSUE,
                    attr,
                    context.getLocation(attr),
                    "ViewIdName建议使用view的缩写_xxx; ${element.tagName} 建议使用 `${expMsg}_xxx`"
                )
            }
        }
    }
​
    companion object {
        val ISSUE: Issue = Issue.create(
            "ViewIdCheck",
            "ViewId命名不规范",
            "ViewIdName建议使用 view的缩写加上_xxx,例如tv_xxx, iv_xxx",
            CORRECTNESS,
            5, Severity.ERROR,
            Implementation(
                ViewIdDetector::class.java,
                RESOURCE_FILE_SCOPE
            )
        )
    }
}

自定义Detector可以实现一个或多个Scanner接口,选择实现哪种接口取决于你想要的扫描范围。
Lint API 中内置了很多 Scanner:

Scanner 类型 Desc
UastScanner 扫描 Java、Kotlin 源文件
XmlScanner 扫描 XML 文件
ResourceFolderScanner 扫描资源文件夹
ClassScanner 扫描 Class 文件
BinaryResourceScanner 扫描二进制资源文件
GradleScanner 扫描Gradle脚本

4. 实现IssueRegistry并添加对应的自定义Issue:

class IMockIssueRegistry: IssueRegistry() {
    override val issues: List<Issue>
        get() = listOf(
            ViewIdDetector.ISSUE
        )
​
}

5. 在module(lint_tools)中对应的build.gradle中配置如下信息:

jar {
    manifest {
        attributes("Lint-registry-v2": "com.imock.lint.IMockIssueRegistry")
    }
}

6. 在需要进行lint检查的module中或者app目录现的build.gradle中引用对应的lint_tools即可使用。

dependencies {
    lintChecks project(path: ':lint-tools')
}

至此你可以试着自己自定义Lint了,相关语法api都可参考lint-checks中提供的Detector实现,来实现自己的Lint检查规则。

拓展一下:

1. 针对Issue.create参数了解一下:

companion object {
    /**
     * Creates a new issue. The description strings can use some simple markup;
     * see the [TextFormat.RAW] documentation
     * for details.
     *
     * @param id the fixed id of the issue
     * @param briefDescription short summary (typically 5-6 words or less), typically
     * describing the **problem** rather than the **fix**
     * (e.g. "Missing minSdkVersion")
     * @param explanation a full explanation of the issue, with suggestions for
     * how to fix it
     * @param category the associated category, if any
     * @param priority the priority, a number from 1 to 10 with 10 being most
     * important/severe
     * @param severity the default severity of the issue
     * @param implementation the default implementation for this issue
     * @return a new [Issue]
     */
    @JvmStatic
    fun create(
        id: String,
        briefDescription: String,
        explanation: String,
        category: Category,
        priority: Int,
        severity: Severity,
        implementation: Implementation
    ): Issue {
        val platforms = computePlatforms(null, implementation)
        return Issue(
            id, briefDescription, explanation, category, priority,
            severity, platforms, null, implementation
        )
    }
}
  • 参数id 唯一的id,简要表面当前提示的问题。
  • 参数briefDescription 简单描述当前问题
  • 参数explanation 详细解释当前问题和修复建议
  • 参数category 问题类别
  • 参数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(其他);

到此这篇关于Android代码检查规则Lint的自定义与应用详解的文章就介绍到这了,更多相关Android代码检查规则Lint内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 详解Android Lint的原理及其使用

    Android Lint 原理及使用详解 Android Lint 是 ADT 16中引入的新工具,用于扫描 Android 项目源中的潜在错误. Lint 是 Android 提供的一个强大的,用于静态扫描应用源码并找出其中的潜在问题的实用工具.lint 工具可以检查你的 Android 项目源文件是否有潜在的错误,以及在正确性.安全性.性能.易用性.无障碍性和国际化方面是否需要优化改进. Lint 既可以用作命令行工具,也可以与 Eclipse 和 IntelliJ 集成在一起.它被设计成独

  • Android TraceView和Lint使用详解及性能优化

    Android lint工具是Android studio中集成的一个代码提示工具,它主要负责对你的代码进行优化提示,包括xml和java文件,很强大.编写完代码及时进行lint测试,会让我们的代码变得非常规范而且避免代码冗余.让我们及时发现代码中隐藏的问题. lint的使用时非常简单的,我看可以用它实现代码布局的优化,Java代码的优化,不过我觉得根本解决问题还是得依赖于开发者的素质. 例子:我们需要删除掉一些无用的变量和布局文件等,这对代码的冗余有很大的帮助. 代码提示我们在6行需要为Ima

  • Android——Android lint工具项目资源清理详解

    Android--Android lint工具项目资源清理 最近维护的项目已经有两年多,经过很多前辈的迭代,项目并没有变得健壮,而变得很臃肿.用Android lint工具清理了一次,清楚了不少废弃的布局和资源. 1.     Android lint工具 可以右键项目,Android tools,退出的时候clear lint markers即可 也可以如图: 2.结果出来了,分析分析 3.xml中view太多,已经超过了80个,影响性能. 布局优化: 尽量使用include.merge.Vi

  • Android代码检查规则Lint的自定义与应用详解

    目录 前言: 什么是Lint 自定义Lint流程: 1. 新创建module,Module类型选择Java or Kotlin Library, 暂时命名lint_tools 2. 在build.gradle中引入lint的依赖 3. 本地创建个资源id命名检查规则,用来规范项目中的id统一命名 4. 实现IssueRegistry并添加对应的自定义Issue: 5. 在module(lint_tools)中对应的build.gradle中配置如下信息: 6. 在需要进行lint检查的modul

  • Android启动内置APK和动态发送接收自定义广播实例详解

    Android启动内置APK和动态发送接收自定义广播实例详解 工作中遇到这样一个需求,需要为按键添加一个亲情号,提供一个接口启动内置的APK,思考再三决定更改Framework,利用广播机制去实现. 一.代码动态自主启动内置APK 我们都知道Android系统为我们提供了很多服务管理类,PackageManager主要是管理应用程序包,通过它就可以获取应用程序信息并构建Intent,启动对应的应用.除此之外Android还未我们提供了一些对应的类来管理相关的xml文件,比如说可以通过Packag

  • Kotlin之自定义 Live Templates详解(模板代码)

    想必大家都知道 android studio 的 live templates 功能,那真是各种方便,比如你想使用 newInstance 去生成一个类的实例: 简直不要太方便! 当今 kotlin 流行起来了,你在使用 kotlin 开发 android 的时候,是不是发现以前用的 logt.loge.newinstance-,这些快捷创建代码片段的方式都不能用了,没关系,来一起自定义吧年轻人~ 打开 android studio >> File >> Settings ,搜索

  • android尺子的自定义view——RulerView详解

    项目中用到自定义尺子的样式: 原代码在github上找的,地址:https://github.com/QQabby/HorizontalRuler 原效果为 因为跟自己要使用的view稍有不同 所以做了一些修改,修改的注释都放在代码中了,特此记录一下. 首先是一个自定义View: public class RuleView extends View { private Paint paint; private Context context; private int maxValue = 500

  • Android使用xml自定义图片实例详解

    Android使用xml自定义图片实例详解 实现效果图: 白色圆角图片 bg_round_rectangle_white.xml <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <!-

  • Android AS创建自定义布局案例详解

    先创建一个title.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" andr

  • Flutter CustomPaint自定义绘画示例详解

    目录 正文 CustomPaint 介绍 绘制点 PointMode3种模式 绘制线 和路径 绘制五子棋 总结 正文 CustomPaint是Flutter中用于自由绘制的一个widget,它与android原生的绘制规则基本一致,以当前Canves(画布)的左上角为原点进行绘制.在有些场景中,我们会需要绘制一些高度定制化的组件,比如 UI 设计师给我们出了个难题 —— 弄一个奇形怪状的边框.这个时候我们就不能直接使用 Flutter 自带的那些组件了,而是需要手动绘制组件,那就会需要用到 Cu

  • Android进阶Handler应用线上卡顿监控详解

    目录 引言 1 Handler消息机制 1.1 方案确认 1.2 Looper源码 1.3 Blockcanary原理分析 1.4 Handler监控的缺陷 2 字节码插桩实现方法耗时监控 2.1 字节码插桩流程 2.2 引入ASM实现字节码插桩 2.3 Blockcanary的优化策略 引言 在上一篇文章中# Android进阶宝典 -- KOOM线上APM监控最全剖析,我详细介绍了对于线上App内存监控的方案策略,其实除了内存指标之外,经常有用户反馈卡顿问题,其实这种问题是最难定位的,因为不

  • Android中gson、jsonobject解析JSON的方法详解

    JSON的定义: 一种轻量级的数据交换格式,具有良好的可读和便于快速编写的特性.业内主流技术为其提供了完整的解决方案(有点类似于正则表达式 ,获得了当今大部分语言的支持),从而可以在不同平台间进行数据交换.JSON采用兼容性很高的文本格式,同时也具备类似于C语言体系的行为. JSON对象: JSON中对象(Object)以"{"开始, 以"}"结束. 对象中的每一个item都是一个key-value对, 表现为"key:value"的形式, ke

  • Android 带清除功能的输入框控件实例详解

    Android 带清除功能的输入框控件实例详解 今天,看到一个很好的自定义输入框控件,于是记录一下. 效果很好: 一,自定义一个类,名为ClearEditText package com.example.clearedittext; import android.content.Context; import android.graphics.drawable.Drawable; import android.text.Editable; import android.text.TextWatc

随机推荐