使用Lint 和 Annotations来提升代码质量
使用 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 文件
可以使用lint.xml来指定Lint的检查属性。手动创建这个文件的话,把它放到project的根目录下。 如果你是通过Android Studio来配置检查属性,lint.xml会自动创建在project根目录下。
lint.xml结构如下,由
父tag包含一个或多个
子元素组成,每个
指定一个唯一的由Lint定义过的id属性。
<?xml version="1.0" encoding="UTF-8"?><lint> <issue id="IconMissingDensityFolder" severity="ignore" /> <issue id="ObsoleteLayoutParam"> <ignore path="res/layout/activation.xml" /> <ignore path="res/layout-xlarge/activation.xml" /> issue> <issue id="UselessLeaf"> <ignore path="res/layout/main.xml" /> issue> <issue id="HardcodedText" severity="error" />lint>
在Java和XML源文件中配置lint 检查
可以在java和XML源文件中禁用Lint检查.
在java文件中
@SuppressLint
注解可以让Java class 或者方法不用Lint检查。关闭”NewApi”问题的检查
@SuppressLint("NewApi")@Overridepublic 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 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()。
@CallSuperprotected 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
提高代码质量-工具篇
更多相关文章
- Android(安卓)databinding(详解三)--自定义属性使用
- android 莫名出现Conversion to Dalvik format failed: Unable t
- Android应用的自动升级、更新模块的实现
- 【Android(安卓)界面效果34】Android里Service的bindService()和
- android电话流程(打电话,接电话,挂断电话)
- Android(安卓)Studio使用Volley
- Android(安卓)Handler机制之Handler 、MessageQueue 、Looper
- Android(安卓)ContentProvider总结
- Android(安卓)控件框架