アノテーションとは
@Override、@NonNull、@Nullable
よく使うアノテーションだけどそもそも何者?
オラクル曰くこう
Annotations, a form of metadata, provide data about
a program that is not part of the program itself.
Annotations have no direct effect on the operation of the code they annotate.
つまりこんな感じ。
- メタデータ(付属情報である)
- プログラム自体ではない
- コードの処理に直接影響は与えない
アノテーションを定義する
一番簡単な方法はこう
定義して
public @interface SampleAnnotation {}
使う!
@SampleAnnotation
アノテーションには引数も渡せる
アノテーションの定義に引数を渡す場合はこう
引数(argStrとargInt)を定義して
public @interface SampleAnnotation {
String argStr();
int argInt() default 0;
}
渡す!
@SampleAnnotation (
argStr = "sample",
int = 1
)
コンパイル時にアノテーションを処理する
引数を渡せるって? 引数渡してだから何?
そんなときにAnnotationProcessorというものがあります。
AnnotationProcessorを使うことでコンパイル時にアノテーションを処理できます。
例えば、ButterKnifeを例にアノテーションの引数に渡したものがどう処理されているかを
見ていくとわかりやすいです。
詳しくは下記のサイトがわかりやすく説明していますのでここではざっくりと説明します。
http://qiita.com/kgmyshin/items/7713a07da86fafec056e
ButterKnife
ButterKnife自体は下記のようにViewをいちいちfindViewByIdで参照しなくても、
変数にアノテーション付与することで簡単にViewを生成できるライブラリです。
@InjectView(R.id.sample)
View mSampleView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_activity);
ButterKnife.inject(this);
}
なぜ、findViewByIdはいらないのか?
アノテーションにResouceIdを指定することで、コンパイル時にfindViewByIdしてmSampleViewに代入するための処理をButterKnife.inject()内に用意しています。
余談
最終的にはfindViewByIdをinject内で行うので記述は楽になりますが、
処理が軽くなることはないような気がします。
具体的にどうやって?
ButterKnife.inject(this)を呼ぶことで最終的に「対象Activity$$ViewInjector」という
クラスのinjectメソッドを呼び出すようになっています。
ButterKnifeでは、この「対象Activity$$ViewInjector」をコンパイル時に生成するために主題のAnnotationProcessorを使っています。
AnnotationProcessorとは
ProcessorまたはAbstractProcessorクラスを継承することでOverrideしたprocess()というメソッドがコンパイル時に動きます。
このような仕組みをAnnotationProcessorというようです。
そして、ButterKnifeの場合、ButterKnifeProcessorというクラスがそれにあたります。
このButterKnifeProcessorのprocess()内でinjectメソッドを持つ「対象Activity$$ViewInjector」というクラスファイルを生成する処理を行っています。
まとめ
・アノテーションはメタデータ
・引数が渡せる
・AnnotationProcessorでコンパイル時に処理を行える