Edited at

新しく使えるようになった13個のSupport Annotations

More than 3 years have passed since last update.

Google I/OのWhat’s New in Android Development Tools(動画の24:07くらいから)で紹介されたsupport-annotations 22.2から使えるようになった新しい13のアノテーションについてメモ。


環境

今回、お試しした環境は以下のとおり。

Android Mをターゲットにしていますがそれ以前のバージョンでも使えるのではないかと思います。


  • Mac OS X: 10.10.3

  • Android Studio: 1.3 Preview 2

  • Gradle plugin: 1.3.0-beta2

  • Build tools: 23.0.0 rc2

  • Target SDK: MNC


使い方

biuld.gradleのdependenciesに以下を追加するだけです。

compile 'com.android.support:support-annotations:22.2.0'


@WorkerThread, @UiThread, @MainThread, @BinderThread

この4つのアノテーションはメソッドの実行スレッドを明示することができます。

例えば、

    @WorkerThread

private void myWorkerMethod(TextView textView) {
textView.setText("Worker Thread!");
}

このように@WorkerThreadでアノテーションしたメソッド内でUI操作を書くと「UIスレッドで呼んでね!」と怒ってくれます。

@WorkerThread

逆に次のようにUIスレッドで動作させることを明示しているメソッドをAsyncTaskの中などで呼ぼうとした時にも怒ってくれます。

    @UiThread

private void myUiMethod(TextView textView) {
textView.setText("UI Thread!");
}

public AsyncTask testTask() {
return new AsyncTask() {
@Override
protected Object doInBackground(Object[] params) {
myWorkerMethod(mTextView);
myUiMethod(mTextView);
return null;
}
};
}

@UiThread


@UiThread@MainThreadの違い

ドキュメントによると、極めて稀なケースではあるがアプリが別ウインドウを実行するためにメインスレッドとは別のUIスレッドを作ることがあるらしい。

なので、普通に使っている分には@UiThread@MainThreadの違いを気にする必要は無さそう。


Tips

例としてメソッドにアノテーションを付与してみましたが、Viewの拡張クラスのようにクラス全体がUIスレッドで動作することが要求される場面ではクラスにアノテーションを付けることも可能とのこと。


@Size

メソッドの引数にサイズの最小値、最大値を指定したり、

    private void log(@Size(min = 1, max = 23) String tag) {

Log.d(tag, "Logging!");
}

private void sizeTest() {
log("This is too long text for tag");
log("Appropriate tag");
log("");
}

MaxMin

配列のサイズを指定したり、

    public void setViewPosition(@Size(2) int[] position) {}

private void sizeTest2() {
int[] position = new int[3];
setViewPosition(position);
}

ArraySize

配列のサイズを2の倍数に指定したり(x,y座標の組み合わせを受け取りたいときとか)、

    public void setViewPosition2(@Size(multiple = 2) int[] positions) {}

public void sizeTest3() {
int[] positions = new int[5];
setViewPosition2(positions);
}

というように引数のサイズを指定することが出来ます。

...が 不具合? なのか自分の環境では配列サイズの条件にマッチする引数を渡してもエラーになる...

Error

追記

本日配信されたAndroid Studio 1.3 Preview 3で配列サイズの条件を満たしていてもエラーになる不具合が解消されていました。

AS1.3


@IntRange, @FloatRange

メソッド引数に渡される値の許容範囲を指定できます。

    private void setViewAlpha(@FloatRange(from = 0.0, to = 1.0) float alpha) {}

private void testRange() {
setViewAlpha(0.5f);
setViewAlpha(100f);
}

range.png


@ColorInt

色の情報を渡すとき、リソースIDなのか色のInt値なのか区別を付けるためのアノテーションです。

@ColorIntを付けた引数にリソースIDを渡すとエラーになります。

    private void setViewColor(@ColorInt int color) {}

private void testColorInt() {
setViewColor(Color.BLUE);
setViewColor(android.R.color.black);
}

ColorInt


@CallSuper

継承先のクラスでメソッドをオーバライドした際に、superを呼ぶ必要が有ることを明示できます。


public class BaseClass {
@CallSuper
public void baseMethod() {
Log.d("TEST", "You need call super!");
}
}

public class ExtendedClass extends BaseClass {
@Override
public void baseMethod() {
Log.d("TEST", "Do I have to call super?");
}
}

CallSuper


@CheckResult

このアノテーションを付けたメソッドの返り値を使用していないと怒られるようになります。

また、他のメソッドを使うようにサジェストすることもできます。

    @CheckResult(suggest = "#validate(int)")

private boolean isValid() {
return true;
}

private boolean validate(int id) {
{
// do validate something
}
return true;
}

private void testCheckResult() {
isValid();
}

CheckResult


@RequiresPermission

パーミッションが必要なメソッドを明示できます。

指定の仕方も「どれか」「ぜんぶ」など色々な指定の仕方ができるようです。

    @RequiresPermission(anyOf = {

Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION})
private void getLocation() {}

@RequiresPermission(allOf = {
Manifest.permission.READ_CALENDAR,
Manifest.permission.WRITE_CALENDAR})
private void updateCalendar() {}

private void testPermission() {
getLocation();
updateCalendar();
}

Permission

また、エラーになっている箇所で"⌥+Enter"すると、AndroidManifestへのパーミッション追加やパーミッションのチェック処理を追加することができます。

PermissionAnim


@VisibleForTesting

テスト用にクラス、メソッド、フィールドの可視範囲を広げることができます。

とドキュメントには書いているんですが、privateなフィールドやメソッドにこのアノテーションをつけてもテストからはアクセス出来なかったです。

使い方を間違っているのか不具合なのか...うまく使える方、使い方教えてください。

追記

コメント欄で@fkmさんに指摘頂きました。完全に自分のドキュメント読み間違えです。


This annotation lets you declare that a class, method or field is more visible than necessary, in order to be able to access it from tests.


とあるので「テストのためにクラス、メソッド、フィールドが必要以上の可視性を持っていることを明示できる」が正しいです。


@Keep

アプリの最小化時(Proguardのことかな?)に保持すべきメソッドやクラスにアノテーションを付けることができます。

でもまだ使えません!


おわり

うまく使えば入力値やメソッドの使い方をある程度制限することができるので、特に複数人で開発するようなときは期待しない使い方をされることを抑えてバグの混入を減らすのに役立つかもしれません。


参考

Google I/Oのセッション動画: Google I/O 2015 - What's New in Android Development Tools - YouTube

ドキュメント: Support Annotations - Android Tools Project Site