美文网首页
使用Lint 和 Annotations来提升代码质量

使用Lint 和 Annotations来提升代码质量

作者: ShenJC | 来源:发表于2016-08-18 09:33 被阅读383次

    使用 Lint 来检查代码

    在 Android Studio 中使用 lint

    在Android Studio中,当你build app的时候,Lint和IDE 检查会自动运行。

    使用 File > Settings > Editor > Inspections 菜单可以打开检查配置界面

    使用Android Studio,可以在build.gradle文件中添加 lintOptions 属性 可以对Lint 的检查做相关的设置。下面是示例代码:

    android {
        lintOptions {
           // set to true to turn off analysis progress reporting by lint
           quiet true
           // if true, stop the gradle build if errors are found
           abortOnError false
           // if true, only report errors
           ignoreWarnings true
           }
           ...
        }
    

    在指定目录上右击,在右击菜单中选择Analyze > Inspect Code 就可以进行手动的Lint代码检查。

    在命令行中跑 lint

    检查工程目录下的所有文件:

    lint [flags] <project directory>
    

    使用下面命令可以扫描myproject 目录下的所有文件以及子文件。参数MissingPrefix 表示只扫描缺少Android 命名前缀的XML属性。

    lint --check MissingPrefix myproject 
    

    通过命令来查看使用方法和参数:

    lint --help
    

    配置lint

    在Android Studio中配置lint

    有两种方法可以看到Lint的warnings和errors 结果:

    • 编辑器中提示文字。Lint会黄色高亮有问题的代码,或使用红色下划线指示严重的问题。
    • 手动Analyze > Inspect Code 之后,在检查结果窗口中。

    设置默认的Lint 检查:

    1. 打开项目,选择 File > Other Settings > Default Settings,选择 Editor > Inspections.
    2. 在Profile 选项中,选择 Default or Project Default来选择是全局作用域还是project作用域。
    3. 在窗口中进行设置。

    配置手动执行的Lint检查:

    1. 打开项目,选择你要测试的目录。使用Analyze > Inspect Code.
    2. 在指定检查范围弹出框中,选择检查scope和profile。scope指定哪些文件你想要分析,profile指定你想要执行的Lint checks。

    使用配置文件lint.xml

    可以使用lint.xml来指定Lint的检查属性。手动创建这个文件的话,把它放到project的根目录下。 如果你是通过Android Studio来配置检查属性,lint.xml会自动创建在project根目录下。

    lint.xml结构如下,由<lint> 父tag包含一个或多个<issue> 子元素组成,每个<issue> 指定一个唯一的由Lint定义过的id属性。

    <?xml version="1.0" encoding="UTF-8"?>
    <lint>
        <!-- Disable the given check in this project -->
        <issue id="IconMissingDensityFolder" severity="ignore" />
    
        <!-- Ignore the ObsoleteLayoutParam issue in the specified files -->
        <issue id="ObsoleteLayoutParam">
            <ignore path="res/layout/activation.xml" />
            <ignore path="res/layout-xlarge/activation.xml" />
        </issue>
    
        <!-- Ignore the UselessLeaf issue in the specified file -->
        <issue id="UselessLeaf">
            <ignore path="res/layout/main.xml" />
        </issue>
    
        <!-- Change the severity of hardcoded strings to "error" -->
        <issue id="HardcodedText" severity="error" />
    </lint>
    

    在Java和XML源文件中配置lint 检查

    可以在java和XML源文件中禁用Lint检查.

    • 在java文件中
      @SuppressLint 注解可以让Java class 或者方法不用Lint检查。

    关闭"NewApi"问题的检查
    @SuppressLint("NewApi") @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);
    关闭"ParserError"的问题检查
    @SuppressLint("ParserError") public class FeedProvider extends ContentProvider {
    关闭Java文件中的所有的检查
    @SuppressLint("all")

    • 在XML文件中
      使用tools:ignore属性来禁止XML文件制定区域的Lint 检查。父控件的ignore属性会被子控件继承。
      关闭"UnusedResources "的问题检查。
          <LinearLayout
              xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              tools:ignore="UnusedResources" >
          
              <TextView
                  android:text="@string/auto_update_prompt" />
          </LinearLayout>
      
      关闭多个问题检查
      tools:ignore="NewApi,StringFormatInvalid"
      
      关闭所有的问题检查
      tools:ignore="all"
      

    使用Annotations来检查代码 (Support-Annotations library)

    Annotations 可以给代码检查工具提供一些提示,来帮助检查微妙的代码问题。
    Annotations以元数据的方式添加到 变量、参数、一个方法中的输入参数、返回值等。
    当使用了代码检查工具, annotations 可以帮助检查这些问题,比如空指针异常和资源文件类型冲突。

    添加基本的注解

    想要在代码中使用注解,需要添加 Support-Annotations 库。

    • 可以通过Android Studio 来添加
    • 或者直接在gradle.xml中添加
    dependencies {
        compile 'com.android.support:support-annotations:23.3.0'
    } 
    

    添加 Nullness Annotations

    @Nullable and @NonNull annotations 可以检查一个变量、参数或返回值的null情况。

    使用@NonNull 来检查传入的参数不能为空。

    import android.support.annotation.NonNull;
    ...
    
        /** Add support for inflating the <fragment> tag. */
        @NonNull
        @Override
        public View onCreateView(String name, @NonNull Context context,
          @NonNull AttributeSet attrs) {
          ...
          }
    ...
    

    Nullability Analysis

    Android Studio 支持通过nullability 分析来在代码中动态的推断和插入nullness annotations。为空性分析根据贯穿方法树的几个约定来进行扫描:

    • 方法可以返回空
    • 方法不可以返回空。
    • 变量可以为空,比如本地变量和参数。
    • 变量不能为空,比如本地变量和参数。

    这个分析完成后,被检查的地方会动态的加入合适的null annotations。

    在 Android Studio 中 进行 nullability的检查,选择Analyze > Infer Nullity
    Android Studio会插入 @Nullable and @NonNull annotations 在需要检查的位置。在空指针分析完成后,最好检验一下被注入的annotations。

    添加 Resource Annotations

    Resource Annotations 校验传入的参数是否为指定的资源类型
    @StringRes
    @DrawableRes
    @DimenRes
    @ColorRes
    @InterpolatorRes

    import android.support.annotation.StringRes;
    ...
        public abstract void setTitle(@StringRes int resId);
        ...
    

    添加 Thread Annotations

    Thread annotations 校验一个方法是否在指定的线程中被调用。有以下4中类型:
    @UiThread
    @MainThread
    @WorkerThread
    @BinderThread

    @MainThread and the @UiThread 可以互换。

    添加 Value Constraint Annotations

    @IntRange, @FloatRange, @Size 校验传递过来的参数值。

    @IntRange 校验是否在指定的整形范围内。例子说明 alpha 参数包含在 0 ~ 255 之间:

    public void setAlpha(@IntRange(from=0,to=255) int alpha) { … }
    

    @FloatRange 检验是否在指定的浮点型范围内。比如确保alpha参数在0.0 to 1.0之间:

    public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {...}
    

    @Size 校验一个容器或数组的长度。比如,使用@Size(min=1) 来检查一个容器不为空,使用@Size(2)来校验容器确定只有两个值。比如 确定location 数组知识包含一个元素:

    int[] location = new int[3];
    button.getLocationOnScreen(@Size(min=1) location);
    

    添加Permission Annotations

    @RequiresPermission 校验方法调用者的权限。 anyOf 属性用于检查满足一种一个, allOf属性用于检查满足所有 attribute.

    setWallpaper 方法必须要有permission.SET_WALLPAPERS 权限.

    @RequiresPermission(Manifest.permission.SET_WALLPAPER)
    public abstract void setWallpaper(Bitmap bitmap) throws IOException;
    
    @RequiresPermission(allOf = {
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE})
    public static final void copyFile(String dest, String source) {
        ...
    }
    

    添加 CheckResults Annotations

    @CheckResults 校验方法接口或者返回值是否真的被使用了。
    下面的例子表示checkPermissions 方法确定返回值被使用了。如果没使用,就会建议使用 enforcePermission方法来替代。

    @CheckResult(suggest="#enforcePermission(String,int,int,String)")
    public abstract int checkPermission(@NonNull String permission, int pid, int uid);
    

    添加 CallSuper Annotations

    使用@CallSuper 注解 校验 覆写的方法 需要调用父类的实现方法。
    例子,覆写onCreate的方法必须调用super.onCreate()。

     @CallSuper
    protected void onCreate(Bundle savedInstanceState) {
    }
    

    创建Enumerated Annotations

    使用 @IntDef@StringDef 注解 可以创建一个integer 和 string 类型的集合用来校验 其他变量的引用类型,比如传入set中的引用类型。

    import android.support.annotation.IntDef;
    ...
    public abstract class ActionBar {
        ...
        //Define the list of accepted constants
        @IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
    
        //Tell the compiler not to store annotation data in the .class file
        @Retention(RetentionPolicy.SOURCE)
    
        //Declare the NavigationMode annotation
        public @interface NavigationMode {}
    
        //Declare the constants
        public static final int NAVIGATION_MODE_STANDARD = 0;
        public static final int NAVIGATION_MODE_LIST = 1;
        public static final int NAVIGATION_MODE_TABS = 2;
    
        //Decorate the target methods with the annotation
        @NavigationMode
        public abstract int getNavigationMode();
    
        //Attach the annotation
        public abstract void setNavigationMode(@NavigationMode int mode);
    

    译代码的时候,如果mode 类型不在定义中的(NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, or NAVIGATION_MODE_TABS)时,会有警告产生。

    使用flag 可以检查一个参数或者返回值是否引用类型是否在指定的格式中。

    import android.support.annotation.IntDef;
    ...
    
    @IntDef(flag=true, value={
            DISPLAY_USE_LOGO,
            DISPLAY_SHOW_HOME,
            DISPLAY_HOME_AS_UP,
            DISPLAY_SHOW_TITLE,
            DISPLAY_SHOW_CUSTOM
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface DisplayOptions {}
    
    ...
    

    参考文档

    Improve Your Code with Lint
    Improve Code Inspection with Annotations
    support-annotations
    提高代码质量-工具篇

    相关文章

      网友评论

          本文标题:使用Lint 和 Annotations来提升代码质量

          本文链接:https://www.haomeiwen.com/subject/cylvsttx.html