blob: b0d5a228ac701bcbd06551313760cfcbaa23737b [file] [log] [blame]
page.title=Improving Code Inspection with Annotations
@jd:body
<div id="qv-wrapper">
<div id="qv">
<h2>In this document</h2>
<ol>
<li><a href="#adding-nullness">Adding Nullness Annotations</a></li>
<li><a href="#res-annotations">Adding Resource Annotations</a></li>
<li><a href="#thread-annotations">Adding Thread Annotations</a></li>
<li><a href="#value-constraint">Adding Value Constraint Annotations</a></li>
<li><a href="#permissions">Adding Permission Annotations</a></li>
<li><a href="#check-result">Adding CheckResult Annotations</a></li>
<li><a href="#call-super">Adding CallSuper Annotations</a></li>
<li><a href="#enum-annotations">Creating Enumerated Annotations</a></li>
</ol>
<h2>See also</h2>
<ol>
<li><a href="{@docRoot}tools/help/lint.html">lint (reference)</a></li>
<li><a href="{@docRoot}tools/debugging/improving-w-lint.html">Improving Your Code with lint</a></li>
<li><a href="{@docRoot}tools/studio/index.html#annotations">Annotations in Android Studio</a></li>
</ol>
</div>
</div>
<p>Using code inspections tools such as <a href="{@docRoot}tools/help/lint.html">lint</a> can help
you find problems and improve your code, but inspection tools can only infer so much. Android
resource ids, for example, use an {@code int} to identify strings, graphics, colors and other
resource types, so inspection tools cannot tell when you have specified a string resource where
you should have specified a color. This situation means that your app may render incorrectly or
fail to run at all, even if you use code inspection. </p>
<p>Annotations allow you to provide hints to code inspections tools like {@code lint}, to help
detect these, more subtle code problems. They are added as metadata tags that you attach to
variables, parameters, and return values to inspect method return values, passed parameters, and
local variables and fields. When used with code inspections tools, annotations can help you detect
problems, such as null pointer exceptions and resource type
conflicts. </p>
<p>For more information on enabling <a href="{@docRoot}tools/help/lint.html">lint</a> inspections
and running <a href="{@docRoot}tools/help/lint.html">lint</a>,
see <a href="{@docRoot}tools/debugging/improving-w-lint.html">Improving Your Code with lint</a>.</p>
<p>Android supports a variety of annotations for insertion in the methods, parameters, and return
values in your code, for example:</p>
<dl>
<dt>{@link android.support.annotation.Nullable @Nullable}</dt>
<dd>Can be null.</dd>
<dt>{@link android.support.annotation.NonNull @NonNull}</dt>
<dd>Cannot be null.</dd>
<dt>{@link android.support.annotation.StringRes @StringRes}</dt>
<dd>References a <a href="{@docRoot}reference/android/R.string.html"><code>R.string</code></a>
resource.</dd>
<dt>{@link android.support.annotation.DrawableRes @DrawableRes}</dt>
<dd>References a
<a href="{@docRoot}guide/topics/resources/drawable-resource.html"><code>Drawable</code></a>
resource. </dd>
<dt>{@link android.support.annotation.ColorRes @ColorRes}</dt>
<dd>References a <a href="{@docRoot}reference/android/graphics/Color.html"><code>Color</code></a>
resource. </dd>
<dt>{@link android.support.annotation.InterpolatorRes @InterpolatorRes}</dt>
<dd>References a
<a href="{@docRoot}reference/android/view/animation/Interpolator.html"><code>Interpolator</code></a>
resource. </dd>
<dt>{@link android.support.annotation.AnyRes @AnyRes}</dt>
<dd>References any type of <a href="{@docRoot}reference/android/R.html"><code>R.</code></a>
resource. </dd>
<dt><code>@UiThread</code></dt>
<dd>Calls from a UI
<a href="{@docRoot}guide/components/processes-and-threads.html">thread</a>. </dd>
</dl>
<p>For a complete list of the supported annotations, either examine the contents of the
{@link android.support.annotation Support-Annotations} library or use the
auto-complete feature to display the available options for the <code>import
android.support.annotation.</code> statement. The
<a href="{@docRoot}tools/help/sdk-manager.html"> SDK Manager</a> packages the
{@link android.support.annotation Support-Annotations} library in the Android Support Repository
for use with Android Studio and in the Android
<a href="{@docRoot}tools/support-library/index.html">Support Library</a> for use with other Android
development tools.</p>
<p>To add annotations to your code, first add a dependency to the
{@link android.support.annotation Support-Annotations} library. In Android Studio,
add the dependency using the <strong>File &gt; Project Structure &gt; Dependencies</strong> menu
option or your <code>build.gradle</code> file. The following example shows how to add the
{@link android.support.annotation Support-Annotations} library dependency in the
<code>build.gradle</code> file: </p>
<pre>
dependencies {
compile 'com.android.support:support-annotations:22.2.0'
}
</pre>
<p>The {@link android.support.annotation Support-Annotations} library is decorated with the
supported annotations so using this library's methods and resources automatically checks the code
for potential problems.</p>
<p>If you include annotations in a library and use the
<a href="{@docRoot}tools/building/plugin-for-gradle.html"><code>Android Plugin for Gradle</code></a>
to build an Android ARchive (AAR) artifact of that library, the annotations are included as part
of the artifact in XML format in the <code>annotations.zip</code> file. </p>
<p>To start a code inspection from Android Studio, which includes validating annotations and
automatic <a href="{@docRoot}tools/help/lint.html">lint</a> checking, select
<strong>Analyze > Inspect Code</strong> from the menu options. Android Studio displays conflict
messages throughout the code to indication annotation conflicts and suggest possible
resolutions.</p>
<h2 id="adding-nullness">Adding Nullness Annotations</h2>
<p>Add {@link android.support.annotation.Nullable @Nullable} and
{@link android.support.annotation.NonNull @NonNull} annotations to check
the nullness of a given variable, parameter, or return value. For example, if a local variable
that contains a null value is passed as a parameter to a method with the
{@link android.support.annotation.NonNull @NonNull} annotation
attached to that parameter, building the code generates a warning indicating a non-null conflict. </p>
<p>This example attaches the {@link android.support.annotation.NonNull @NonNull} annotation to
the <code>context</code> and <code>attrs</code> parameters to check that the passed parameter
values are not null. </p>
<pre>
import android.support.annotation.NonNull;
...
/** Add support for inflating the &lt;fragment&gt; tag. */
&#64;NonNull
&#64;Override
public View onCreateView(String name, &#64;NonNull Context context,
&#64;NonNull AttributeSet attrs) {
...
}
...
</pre>
<p class="note"><strong>Note:</strong> Android Studio supports running a nullability analysis to
automatically infer and insert nullness annotations in your code. For more information about
inferring nullability in Android Studio, see
<a href="{@docRoot}tools/studio/index.html#annotations">Annotations in Android Studio</a>. </p>
<h2 id="res-annotations">Adding Resource Annotations</h2>
<p>Validating resource types can be useful as Android references to resources, such as
<a href="{@docRoot}guide/topics/resources/drawable-resource.html"><code>Drawables</code></a> and
<a href="{@docRoot}reference/android/R.string.html"><code>R.string</code></a> resources, are
passed as integers. Code that expects a parameter to reference a specific type of resource, for
example <a href="{@docRoot}guide/topics/resources/drawable-resource.html"><code>Drawables</code></a>,
can be passed the expected reference type of <code>int</code>, but actually reference a different
type of resource, such as a <code>R.string</code></a> resource. </p>
<p>For example, add {@link android.support.annotation.StringRes @StringRes} annotations to check
that a resource parameter contains a
<a href="{@docRoot}reference/android/R.string.html"><code>R.string</code></a>
reference. During code inspection, the annotation generates a warning if a <code>R.string</code>
reference is not passed in the parameter.</p>
<p>This example attaches the {@link android.support.annotation.StringRes @StringRes}
annotation to the <code>resId</code> parameter to validate that it is really a string resource. </p>
<pre>
import android.support.annotation.StringRes;
...
public abstract void setTitle(&#64;StringRes int resId);
...
</pre>
<p>Annotations for the other resource types, such as
{@link android.support.annotation.DrawableRes @DrawableRes},
{@link android.support.annotation.DimenRes @DimenRes},
{@link android.support.annotation.ColorRes @ColorRes}, and
{@link android.support.annotation.InterpolatorRes @InterpolatorRes} can be added using
the same annotation format and run during the code inspection. </p>
<h2 id="thread-annotations">Adding Thread Annotations</h2>
<p>Thread annotations check if a method is called from a specific type of
<a href="{@docRoot}guide/components/processes-and-threads.html">thread</a>. The following thread
annotations are supported: </p>
<ul>
<li><code>@UiThread</code> </li>
<li><code>@MainThread</code> </li>
<li><code>@WorkerThread</code> </li>
<li><code>@BinderThread</code>
</ul>
<p class="note"><strong>Note:</strong> The <code>@MainThread</code>
and the <code>@UiThread</code> annotations are interchangeable so
methods calls from either thread type are allowed for these annotations. </p>
<p>If all methods in a class share the same threading requirement, you can add a single
<a href="{@docRoot}guide/components/processes-and-threads.html">thread</a>
annotation to the class to verify that all methods in the class are called from the same type of
<a href="{@docRoot}guide/components/processes-and-threads.html">thread</a>. </p>
<p>A common use of the <a href="{@docRoot}guide/components/processes-and-threads.html">thread</a>
annotation is to validate method overrides in the
<a href="{@docRoot}reference/android/os/AsyncTask.html">AsyncTask</a> class as this class performs
background operations and publishes results only on the UI
<a href="{@docRoot}guide/components/processes-and-threads.html">thread</a>. </p>
<h2 id="value-constraint">Adding Value Constraint Annotations</h2>
<p>Use the <code>@IntRange</code>,
<code>@FloatRange</code>, and
<code>@Size</code> annotations to validate the values of passed
parameters. </p>
<p>The <code>@IntRange</code> annotation validates that the parameter
value is within a specified range. The following example ensures that the <code>alpha</code>
parameter contains an integer value from 0 to 255: </p>
<pre>
public void setAlpha(&#64;IntRange(from=0,to=255) int alpha) { … }
</pre>
<p>The <code>@FloatRange</code> annotation checks that the parameter
value is within a specified range of floating point values. The following example ensures that the
<code>alpha</code> parameter contains a float value from 0.0 to 1.0: </p>
<pre>
public void setAlpha(&#64;FloatRange(from=0.0, to=1.0) float alpha) {...}
</pre>
<p>The <code>@Size</code> annotation checks the size of a collection or
array, as well as the length of a string. For example, use the <code>&#64;Size(min=1)</code>
annotation to check if a collection is not empty, and the <code>&#64;Size(2)</code> annotation to
validate that an array contains exactly two values. The following example ensures that the
<code>location</code> array contains at least one element: </p>
<pre>
int[] location = new int[3];
button.getLocationOnScreen(@Size(min=1) location);
</pre>
<h2 id="permissions">Adding Permission Annotations</h2>
<p>Use the <code>@RequiresPermission</code> annotation to
validate the permissions of the caller of a method. To check for a single permission from a
list the valid permissions, use the <code>anyOf</code> attribute. To check for a set of
permissions, use the <code>allOf</code> attribute. The following example annotates the
<code>setWallpaper</code> method to ensure that the caller of the method has the
<code>permission.SET_WALLPAPERS</code> permission. </p>
<pre>
&#64;RequiresPermission(Manifest.permission.SET_WALLPAPER)
public abstract void setWallpaper(Bitmap bitmap) throws IOException;
</pre>
<p>This example requires the caller of the
<code>updateVisitedHistory</code> method to have both read and write bookmark history permissions. </p>
<pre>
&#64;RequiresPermission(allOf = {
Manifest.permission.READ_HISTORY_BOOKMARKS,
Manifest.permission.WRITE_HISTORY_BOOKMARKS})
public static final void updateVisitedHistory(ContentResolver cr, String url, boolean real) {
...
}
</pre>
<h2 id="check-result">Adding CheckResults Annotations</h2>
<p>Use the <code>@CheckResults</code> annotation to
validate that a method's result or return value is actually used. The following example annotates
the <code>checkPermissions</code> method to ensure the return value of the method is actually
referenced. It also names the
<a href="{@docRoot}reference/android/content/ContextWrapper.html#enforcePermission">enforcePermission</a>
method as a method to be suggested to the developer as a replacement. </p>
<pre>
&#64;CheckResult(suggest="#enforcePermission(String,int,int,String)")
public abstract int checkPermission(@NonNull String permission, int pid, int uid);
</pre>
{@link android.support.annotation.StringDef @StringDef}
<h2 id="call-super">Adding CallSuper Annotations</h2>
<p>Use the <code>@CallSuper</code> annotation to validate that an
overriding method calls the super implementation of the method. The following example annotates
the <code>onCreate</code> method to ensure that any overriding method implementations call
<code>super.onCreate()</code>. </p>
<pre>
&#64;CallSuper
protected void onCreate(Bundle savedInstanceState) {
}
</pre>
<h2 id="enum-annotations">Creating Enumerated Annotations</h2>
<p>Use the {@link android.support.annotation.IntDef @IntDef} and
{@link android.support.annotation.StringDef @StringDef} annotations
so you can create enumerated annotations of integer and string sets to validate other types of code
references, such as passing references to a set of constants. </p>
<p>The following example illustrates the steps to create an enumerated annotation that ensures
a value passed as a method parameter references one of the defined constants.</p>
<pre>
import android.support.annotation.IntDef;
...
public abstract class ActionBar {
...
//Define the list of accepted constants
&#64;IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
//Tell the compiler not to store annotation data in the <code>.class</code> file
&#64;Retention(RetentionPolicy.SOURCE)
//Declare the <code>NavigationMode</code> annotation
public &#64;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
&#64;NavigationMode
public abstract int getNavigationMode();
//Attach the annotation
public abstract void setNavigationMode(&#64;NavigationMode int mode);
</pre>
<p>When you build this code, a warning is generated if the <code>mode</code> parameter does
not reference one of the defined constants (<code>NAVIGATION_MODE_STANDARD</code>,
<code>NAVIGATION_MODE_LIST</code>, or <code>NAVIGATION_MODE_TABS</code>).</p>
<p>You can also define an annotation with a <code>flag</code> to check if a parameter
or return value references a valid pattern. This example creates the
<code>DisplayOptions</code> annotation with a list of valid <code>DISPLAY_</code> constants. </p>
<pre>
import android.support.annotation.IntDef;
...
&#64;IntDef(flag=true, value={
DISPLAY_USE_LOGO,
DISPLAY_SHOW_HOME,
DISPLAY_HOME_AS_UP,
DISPLAY_SHOW_TITLE,
DISPLAY_SHOW_CUSTOM
})
&#64;Retention(RetentionPolicy.SOURCE)
public &#64;interface DisplayOptions {}
...
</pre>
<p>When you build code with an annotation flag, a warning is generated if the decorated parameter
or return value does not reference a valid pattern.</p>