11月 122015
AndroidAnnotationsを使い始めた。
findViewByIdを@ViewById(R.id.button)とか書けたり、@Click(R.id.button)の後に関数を定義でクリックリスナーとして登録されたりとかで便利だった。
1つずつ実行したい
@Backgroundを関数の頭に付けるとその関数は非同期実行されるようになる。AsyncTaskなどを自分で書かなくてすむ。
でも複数の非同期な関数を順番に呼び出したい時があって(例えばWebAPIとか)、一気に実行されたら困る。
順番に実行するには1つ目の関数のコールバックに2つ目の関数を登録するか、Promiseみたいなものを返すとかしなければならなくなる。
なので非同期処理を順番に実行したい時はRxJavaとかjdeferredとか使わないといけないのかな・・とか思ってたけどAndroidAnnotationでも綺麗に書けた。
@Background(serial = “id”)
WorkingWithThreads · excilys/androidannotations Wiki
@Backgroundは何も指定しないと全て並列に動作するのだが、同じserialを指定されたBackgroundは1つずつ実行される。Threadを管理しているBackgroundExecutorがqueueを持っているらしい。
おかげで例えば
(Background) Twitterのscreen name取得
(UiThread) screen nameを画面に表示
(Background) screen nameを使ってアイコン画像取得
(UiThread) アイコンを表示
のような処理を簡単に書ける。
@Backgroundや@UiThreadを付けた関数は値を返す事ができないので、classのメンバ変数を値渡しに使うと
String mSreenName;
@Click(R.id.buttonShowTwitterInfo)
void showTwitterInfo(){
getTwitterScreenNameAsync(); // 1つずつ実行される
getTwitterProfileImageAsync();
}
@Background(serial = "twitter")
void getTwitterScreenNameAsync(){
mScreenName = mTwitter.getScreenName();
displayTwitterScreenName(mScreenName);
}
@UiThread
void displayTwitterScreenName(String name){
mTextViewScreenName.setText("@" + name);
}
@Background(serial = "twitter")
void getTwitterProfileImageAsync() {
User user = mTwitter.showUser(mScreenName);
URL imageUrl = new URL(user.getBiggerProfileImageURL());
Bitmap profileImage = BitmapFactory.decodeStream(imageUrl.openConnection().getInputStream());
displayTwitterProfileImage(profileImage);
}
@UiThread
void displayTwitterProfileImage(Bitmap image){
mImageViewProfile.setImageBitmap(image);
}
まあなんとか我慢できる程度に読みやすいコードになる。やっぱりPromiseみたいに値をつないで渡していけた方がいいけど