AndroidStudio代码检查,Lint检查,还有注解

Posted Iaouei

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AndroidStudio代码检查,Lint检查,还有注解相关的知识,希望对你有一定的参考价值。

一,IntelliJ 代码检查

IntelliJ IDEA的具有强大,快速,灵活的静态代码分析。它可以检测编译器和运行时错误,提出改进和完善,甚至在编译之前。

代码检查基础(Code analysis basics)

IntelliJ IDEA的具有强大,快速,灵活的静态代码分析。它可以检测编译器和运行时错误,提出改进和完善,你甚至编译之前。

只要你有一些无效引用的代码,未使用的代码,非本地化的字符串,未完成的方法,内存泄漏,甚至拼写问题 - 你都会很快找到它。

IntelliJ IDEA的代码分析是灵活配置。您可以启用/禁用每个代码审查,并改变其严重程度, 创建自定义审查的配置文件,在不同的范围适用于不同的审查,指定不审查的代码块等等.

可以以几种方式进行的分析:

默认情况下,IntelliJ IDEA的分析所有打开的文件,并强调就在编辑器中检测到的所有代码问题。在编辑器的右侧,可以看到整个文件(在右上角的图标)的分析状​​态:
当检测到错误时;在警告的情况下 ; 如果一切是正确的 .
或者,也可以在指定的范围内,可以是作为整个项目的大批量模式下运行代码分析。
如果有必要,你可以在一个特定的范围内应用单码检查。
对于大多数的检测代码问题,IntelliJ IDEA的提供快速修复建议。您可以通过按 F2从一个审查有问题的代码跳到下一个有问题的代码,Shift+F2跳到上一个。

Inspection severity(严重程度)

审查严重性指示如何认真对待检测有问题的代码,并确定如何将检测的问题在编辑器中突出显示。默认情况下,每次检查有以下严重性级别之一:

服务器问题
Typo
Info
Weak Warning
Warning
Error
还可以增加或减少每次检查的严重性级别。也就是说,你可以强制IntelliJ IDEA的显示一些警告视为错误或弱警告。以类似的方式,将最初考虑弱警告可以显示为警告或错误,或者仅仅作为信息

您还可以配置用于显示的每个级别的颜色和字体样式。此外,你可以创建自定义的严重级别,并设置他们为专项检查。.

如果有必要,可以设置在不同的范围相同的检查不同的严重程度。

所有修改上述检查保存在目前在检查设置中选择的检查信息和当使用该信息适用。

欲了解更多信息和程序的说明,请向下更多阅读。

Inspection scope(范围)

默认情况下,所有启用的代码检查适用于所有项目文件。如果有必要,可以单独为不同的范围配置每个代码检查(启用/禁用,改变它的严重程度和期权)。这样的配置,像任何其他检查设置,作为特定配置文件的一部分被保存并应用。
有可能是复杂的情况下,当检查有不同的范围相关联的不同配置。当这样的检查在属于部分或全部范围的文件执行时,优先级最高的具体范围配置的设置被应用。优先级由检查的特定范围的配置的检验设置的相对位置来定义:最上面的配置具有最高优先级。
了解更多信息和程序的说明,请参阅为不同的范围配置检测。

code inspections示例

通过代码分析所涉及的最常见的任务是:

寻找可能的bugs.
检测性能问题。
查找死代码。
改进代码结构和可维护性。
符合编码规则和标准。
符合规格。
寻找可能的bugs
IntelliJ IDEA的分析您所键入的代码,并能够发现可能的即时非编译错误。下面是这种情况的例子。

Example. 可以在运行时被抛出潜在NPE
Before

此处第一 if条件有可能导致一个空指针异常,在第二个 if处抛出,因为不是所有的情况下都包括在内。在这一点上,以避免一个空指针在运行时期间被抛出增加一个断言将是一个好主意。

After

这样,正是我们从意向行动得到的。

查找死代码
IntelliJ IDEA的突出了所谓的死代码编辑器件。这是应用程序运行期间从不执行的代码。也许,在你的项目甚至不需要这部分代码。视情况,这样的代码可被视为一个错误或作为冗余。反正它降低了应用性能和维护过程复杂化。下面是一个例子。

例如,所谓恒定的条件( constant conditions) - 条件是从来没有见过或总是真实的。在这种情况下,相关代码不可达并且实际上是一个死代码。


IntelliJ IDEA的突出if条件,因为它是总是true。所以代码别的包围的部分实际上是一个死代码,因为从不执行它。

高亮显示未使用的声明(Unused declarations)

IntelliJ IDEA的也能即时突出显示整个项目Unused declarations Java类,方法和通过未使用的声明字段.
For more examples of code inspections use, refer tohttp://www.jetbrains.com/idea/documentation/static_code_analysis.html

访问检查设置(Accessing Inspection Settings)

检查和检查配置文件是在检查设置页面进行编辑。 IntelliJ IDEA的提供了多种方式来访问检查设置。

要访问检查和配置文件的设置,请执行下列操作之一

Open the Settings / Preferences Dialog by choosing File | Settings for Windows and Linux or IntelliJ IDEA | Preferences for OS X, and click Inspections underEditor.
在主工具栏,点击 img, ,然后展开编辑器节点,然后单击检查。
点击状态栏上的当前配置文件的图标

然后单击配置检查Configure inspection 链接 。

在编辑器中,打开建议列表中,单击右箭头,然后选择在子菜单编辑检查配置文件设置。

在检查工具窗口中,单击工具栏上的编辑设置 settings 或使用相应的快捷菜单命令。

Customizing Profiles(自定义配置)

通过Manage下拉列表选项可以复制,重命名,添加描述,导出,导入配置文件。

对于不同的作用域配置检查(Configuring Inspection for Different Scopes)

定义范围的顺序

要定义范围的顺序,请按照下列步骤

在设置/首选项对话框的检查页面,点击按钮 In All Scopes:

从范围下拉列表选择. Edit Scopes Order…
在打开的作用域订单对话框,选择所需的范围,然后单击向上和向下箭头

配置检查严重程度

更改检查严重程度

在检查的设置,选择所需的 profile. 与配置文件相关联的检查显示在下拉列表中。
选择所需的检查。如果这个检查是禁用的,选择旁边的复选框。
从检查的,或从右边的严重性选择上下文菜单中选择所需的严重性:

需要注意的是检查,其状态相对于默认值改变,所有的分组节点用蓝色突出显示。
Apply更改。修改后的检查现在将有新的严重性级别时使用此配置文件。
为不同范围的检查更改严重程度

选择所需的个人资料和检查。
点击下拉列表 In All Scopes, 并选择要更改检查严重程度范围:

IntelliJ IDEA的显示了两个范围严重性:选择了的一个和在其他地方
点击严重性下拉列表中选择范围,然后从下拉列表中选择适当的严重性级别:

更改高亮风格为特定的严重性级别

请执行下列操作之一:
在设置/ Preferences对话框中,选择 Editor | Colors & Fonts -> General, 然后选择对应于期望级别的样式。
在检查的设置,选择所需的检查,然后从严重程度Severity 选择Edit severities。
接着,在 Severities Editor 打开对话框中,选择所需的级别,然后点击Editor | Colors & Fonts.
无论哪种方式,你会看到与此严重性关联的 Colors and Fonts。
配置的颜色和字体样式是必要的并且apply更改。 与相应的严重性所检测的问题现在将使用修改样式编辑器时使用的当前轮廓被突出显示。

定义自定义级别

在检查的设置,选择所需的检查和从 Severity selector选择 Edit severities . .
在打开的Severities Editor 对话框, 点击 add.png:

在New Highlight Severity 对话框中输入新的严重性键入名称。

定制严重性加到严重性的列表。
使用控件严重性列表右侧的新的严重性指定颜色和字体设置。
使用 Up arrowUp.png 和 Down arrowDown.png 改变新的严重性的优先级。
Apply变化. 新的级别现在可为当前配置文件中的所有检查。您可以将其分配给特定的检查,并得到相应的代码问题凸显,在编辑器中指定的样式。
如果有必要,你可以通过在Severities Editor,然后点击 delete.png.选择稍后删除自定义级别。

您不能更改预定义的严重性级别的优先级,或将其删除。

二,代码优化工具:Lint

除了通过满足其功能要求测试代码,它还有个重要的作用是确保代码没有结构方面的问题。结构不佳的代码可以影响Andr​​oid应用程序的可靠性和效率,使代码更难维护。例如,如果XML资源文件包含未使用的命名空间,会占用空间,并会导致不必要的处理. 其他结构性问题,如使用未由目标API版本支持的或API调用弃用的元素,可能会导致代码无法正确运行。

概述

android Studio 提供一个代码扫描工具, Lint,它可以帮助轻松识别并与纠正代码的结构质量问题,而无需执行应用程序或写任何测试用例。 该工具检测到的每个问题会报道描述消息和严重程度,这样就可以很快优先处理关键的改进。还可以配置问题的严重程度忽略不相关的项目的问题,或提高级别。该工具具有命令行端口,让您可以轻松地将它集成到自动化测试过程。

Lint 工具检查您的Andr​​oid项目源文件的正确性,安全性,性能,可用性,可访问性和国际化等相关潜在的bug并且优化改进 。您可以通过命令行或在Android Studio中运行lint。

Note:在Android Studio,为简化代码审查 附加IntelliJ代码检查。

Figure 1显示了Lint工具如何处理应用程序源文件。
.

Android Studio运行lint

在 Android Studio 中,每次构建应用的时候,配置好的 lint 和 IDE 检查会自动运行。因为 Android Studio 是 Intellij idea 社区版本上改的,所以 lint 会和 Intellij 的 IDE 检查一起运行来精简代码审查。

Note: 如果想查看或者修改检查的严格程度,打开设置页面:

在 Android Studio 里,你可以指定某个构建版本来运行 lint,也可以为所有的构建版本运行 lint 检查,一切都在 build.grade 里指定。你也可以在 build.grade 里的 android 设置里添加 lintOptions 属性,比如:

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 [flags] <project directory>

比如,你可以使用下面的命令,扫描 myproject 目录以及子目录。MissingPrefix 告诉 lint 只扫描那些没加 Android 命名空间前缀的 XML 的属性。

lint --check MissingPrefix myproject 

用 lint –help 查看所有的选项:

lint --help

lint输出示例

$ lint Earthquake

Scanning Earthquake: ...............................................................................................................................
Scanning Earthquake (Phase 2): .......
AndroidManifest.xml:23: Warning: <uses-sdk> tag appears after <application> tag [ManifestOrder]
  <uses-sdk android:minSdkVersion="7" />
  ^
AndroidManifest.xml:23: Warning: <uses-sdk> tag should specify a target API level (the highest verified version; when running on later versions, compatibility behaviors may be enabled) with android:targetSdkVersion="?" [UsesMinSdkAttributes]
  <uses-sdk android:minSdkVersion="7" />
  ^
res/layout/preferences.xml: Warning: The resource R.layout.preferences appears to be unused [UnusedResources]
res: Warning: Missing density variation folders in res: drawable-xhdpi [IconMissingDensityFolder]
0 errors, 4 warnings.

配置lint

lint 默认会把它支持的检查都跑一遍。你可以自己配置哪些问题需要检查,也可以自己指定这些问题的严重性。比如,你可以不检查那些和项目无关的问题、降低那些不是很严重的问题的严重程度。

你可以配置 lint 检查 :

整个项目
按项目模块
按产品模块
按测试模块
按打开的文件
按类的层级
从版本控制器的角度

Android Studio中配置Lint

有两种方法可以看到Lint的warnings和errors 结果:
- 编辑器中提示文字。Lint会黄色高亮有问题的代码,或使用红色下划线指示严重的问题:

- 手动Analyze > Inspect Code 之后,在检查结果窗口中:

设置默认的Lint 检查:
1. 打开项目,选择 File > Other Settings > Default Settings,选择 Editor > Inspections.
2. 在Profile 选项中,选择 Default 或者 Project Default来选择是全局作用域还是project作用域。
3. 在窗口中进行设置。

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

配置lint文件

在 Android 项目根目录创建 lint.xml。如果你用 Android Studio 配置的,会自动放在你的 Android 项目下。lint.xml 使用如下格式:

<?xml version="1.0" encoding="UTF-8"?>
    <lint>
        <!-- list of issues to configure -->
</lint>

为根节点,然后包含了很多 子节点。每个 有一个唯一的 id 属性。你可以通过修改 这个 tag 的 severity 属性值,来决定是否要检查这个问题或者改变它的严重程度。

Tip: 试试看 lint –list 命令,你会找到所有支持的 issue 和 他们的 ID。

.

Sample lint.xml file

<?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中配置

关闭lint:添加@SuppressLint 注解.

下面的例子就是告诉你,对于 onCreate 方法不需要做 NewApi 的检查。lint 就会略过这个方法,但是这个类中的其他方法还是会做NewApi 的检查。.

@SuppressLint("NewApi")
@Override
public void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

下面的例子是说,对于 FeedProvider 这个类不需要做 ParserError 的检查::

@SuppressLint("ParserError")
public class FeedProvider extends ContentProvider 

啥都不查:

@SuppressLint("all")

XML中配置

使用 tools:ignore 这个属性关闭 lint 检查。当然你必须包含下面这个命名空间:

namespace xmlns:tools="http://schemas.android.com/tools"

下面这个例子告诉你关闭 LinearLayout 这个元素的 UnusedResources 的检查。 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"

三,优化代码检查:注解

使用代码检查工具(例如Lint)能帮助我们找到一些问题并且可以提高我们代码的质量,检测工具只能做这么多。Android的资源ID,例如,使用int引用字符串,图形,颜色和其他资源类型,所以,当你是否指定你应该指定颜色的字符串资源检测工具也说不清。这种情况意味着,你的应用程序可能会错误地呈现或无法正常运行,即使你使用代码检查。

这时就需要注解来提高优化代码,它们作为附加数据添加到变量,参数和检查方法的返回值,传递的参数和局部变量和范围。

当注解与代码检查工具一块使用,注解可以帮助您检测这些问题,如空指针异常和资源类型的冲突。Android支持用于插入方法中,参数和返回值的各种注释。
运行同Android Studio中配置Lint。

基础

要想在代码中添加注解,首先在项目中要添加有注解库依赖:

如在 build.gradle文件添加有support-annotations 注解库依赖.

dependencies 
    compile 'com.android.support:support-annotations:23.3.0'

Support-Annotations 定义有可以用来作为修饰的注解,所以使用这个库的方法和资源会自动的检查代码潜在的问题 。

Nullness注解

添加 @Nullable 和 @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) 
      ...
      
....

资源注解

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

另外 @DrawableRes, @DimenRes, @ColorRes, and @InterpolatorRes 同样用法

线程注解

调用的方法是否来自指定线程. 线程的注解有:

@UiThread
@MainThread
@WorkerThread
@BinderThread
注意:@MainThread和@UiThread注解是可以相互交换的,因此方法调用这些类型的注解是被允许的。

如果所有的方法要求使用同一个线程,你可以增加一个单例线程注解在类中所有方法来验证相同类型的线程。

一个常见的线程注解是验证是否在UI线程上进行异步任务类的方法重写后台运行和发布结果。

值约束注解

使用 @IntRange, @FloatRange, and @Size 约束值的范围.

public void setAlpha(@IntRange(from=0,to=255) int alpha)  … 
public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) ...

The @Size检查 collection , array, string的长度.例如可以使用 @Size(min=1)检查是不是空, @Size(2) 约束有长度为2:

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

权限注解

使用 @RequiresPermission 检查是否有某一个权限 ,使用 anyOf 检查是否有某些权限中的一个. 使用 allOf 检查是否有某些权限.

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

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

CallSuper注解

使用 @CallSuper 子类重写的方法也需要调用父类方法(即此注解的方法).

@CallSuper
protected void onCreate(Bundle savedInstanceState) 

枚举注解

使用 @IntDef 和@StringDef 限制枚举参数类型.

import android.support.annotation.IntDef;
...
public abstract class ActionBar 
    ...
    //声明枚举,数据接收的类型为int
    @IntDef(NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS)

    //告诉编辑器不要在 .class文件中存储注解数据
    @Retention(RetentionPolicy.SOURCE)

    //声明NavigationMode注解
    public @interface NavigationMode 

    //声明常量
    public static final int NAVIGATION_MODE_STANDARD = 0;
    public static final int NAVIGATION_MODE_LIST = 1;
    public static final int NAVIGATION_MODE_TABS = 2;

    //使用这个注解声明目标方法
    @NavigationMode
    public abstract int getNavigationMode();

    //关联这个注解
    public abstract void setNavigationMode(@NavigationMode int mode);

当 build 这段代码, 如果参数不是指向这些常量中的一个会警告 (NAVIGATION_MODE_STANDARD,NAVIGATION_MODE_LIST, or NAVIGATION_MODE_TABS).

也可以使用flag声明一个注解,检查参数或返回值是否指向一个可用的模式. 下面的例子创建DisplayOptions注解,通过一列 DISPLAY_ constants.

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 

...

当 build 这段代码, 如果参数或返回值不是指向这些常量中的一个会警告

只是简单翻译叙述,语句不是很通顺,建议阅读

jetbrains
Improve Your Code with Lint

以上是关于AndroidStudio代码检查,Lint检查,还有注解的主要内容,如果未能解决你的问题,请参考以下文章

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

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

Android Lint——内嵌于Android Studio的代码优化工具

Android Lint 检查中的“命名空间未绑定”

错误记录Android Studio 编译时 lint 检查报错 ( Could not resolve junit:junit:4.+. )

Lint 错误:可疑的相等检查:在 Object DiffUtilEquals 中未实现 equals()