古くからある、AndroidのHandlerとHandlerThreadについて、動作を検証する。
いわゆる、自分用メモ(必要に応じ、近時の非同期ライブラリなども随時追記していく)。
1.メッセージをあるところで同期したい。
素のJavaでのThreadを扱う時には、Thread間のメッセージの同期はThread#join()メソッドを使って行う。同じようなことをAndroidのDialog表示において、標準ライブラリのみを活用して行いたい。
素のJavaでのメインスレッドと新スレッドとの間のメッセージのやり取りは、こんな感じ。
class Main {
public static void main(String[] args) {
System.out.println(Thread.currentThread() + ": Start. (A)");
try {
Thread th = new Thread() {
public void run() {
try {
System.out.println(Thread.currentThread() + ": Start. (B)");
for (int i = 0; i < 20; i++) {
System.out.println(this + ": i = " + i);
Thread.sleep(10);
}
System.out.println(Thread.currentThread() + ": End. (B)");
} catch (InterruptedException e) {
System.out.println(e);
}
}
};
th.start();
System.out.println(Thread.currentThread() + ": Start2. (A)");
Thread.sleep(20);
System.out.println(Thread.currentThread() + ": Cont. (A)");
th.join(); //**ここで同期**
System.out.println(Thread.currentThread() + ": 同期後①. (A)");
} catch (InterruptedException e) {
System.out.println(e);
}
System.out.println(Thread.currentThread() + ": 同期後②. (A)");
}
}
実行結果
Thread[main,5,main]: Start. (A)
Thread[main,5,main]: Start2. (A)
Thread[Thread-0,5,main]: Start. (B)
Thread[Thread-0,5,main]: i = 0
Thread[Thread-0,5,main]: i = 1
Thread[Thread-0,5,main]: i = 2
Thread[main,5,main]: Cont. (A)
Thread[Thread-0,5,main]: i = 3
Thread[Thread-0,5,main]: i = 4
Thread[Thread-0,5,main]: i = 5
Thread[Thread-0,5,main]: i = 6
Thread[Thread-0,5,main]: i = 7
Thread[Thread-0,5,main]: i = 8
Thread[Thread-0,5,main]: i = 9
Thread[Thread-0,5,main]: i = 10
Thread[Thread-0,5,main]: i = 11
Thread[Thread-0,5,main]: i = 12
Thread[Thread-0,5,main]: i = 13
Thread[Thread-0,5,main]: i = 14
Thread[Thread-0,5,main]: i = 15
Thread[Thread-0,5,main]: i = 16
Thread[Thread-0,5,main]: i = 17
Thread[Thread-0,5,main]: i = 18
Thread[Thread-0,5,main]: i = 19
Thread[Thread-0,5,main]: End. (B)
Thread[main,5,main]: 同期後①. (A)
Thread[main,5,main]: 同期後②. (A)
参考 Javaのjoinメソッド
http://d.hatena.ne.jp/hyuki/20090222/java
2 AndroidのActivityなどで情報の同期
Androidで、カメラでのQRコード読取結果をあるところで取得する、メッセージダイアログの選択結果をあるところで取得するといった場合も、Threadクラスを拡張したHandlerThreadが使えるはず。
注、非同期系の便利ライブラリは一旦忘れる。
参考 Androidのカメラ関係のメソッドを非同期で実行したい
http://serenegiant.com/blog/?p=51
出発点としては、
別スレッドでキュー管理(Handler, Looper, HandlerThread)
http://daichan4649.hatenablog.jp/entry/20111004/1317724067
で書かれている以下のあたりが参考になる。
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
// 新スレ生成 -> 開始
HandlerThread handlerThread = new HandlerThread("other");
handlerThread.start();
// HandlerがhandlerThreadのLooperを取得。
Handler handler = new Handler(handlerThread.getLooper());
handler.post(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
スレッド名"other"があるタイミングで取得できることは分かる。では、取得タイミングをどう制御するのか。
HandlerとLooperが登場する。
参考
http://mixi-inc.github.io/AndroidTraining/fundamentals/2.12.handler-and-looper.html
メインスレッド用のLooperを取得する場合は以下のようにします。
Looper looper = Looper.getMainLooper();
...
Looperに対してメッセージを送る役割を担っているのがHandlerです。...メインスレッドの Looper にメッセージを送るHandlerインスタンスを生成する場合は、以下のようにします。
Handler handler = new Handler(Looper.getMainLooper());
参考
https://realm.io/jp/news/android-thread-looper-handler/
3 お題。アラートダイアログの選択結果を、あるタイミングで取得したい
コピペしてすぐ使えるアラートダイアログ集
http://qiita.com/suzukihr/items/8973527ebb8bb35f6bb8
などを参考に、各種ダイアログでの選択結果をHandlerとHandlerThreadとで扱いたい。
(ダイアログを生成する呼び出し元でしたいこと)
HandlerThread th = new HandlerThread() {
public void run() {
try {
ここで、ダイアログからの「選択結果」を待つ(数秒間を想定)
}
} catch (InterruptedException e) {
System.out.println(e);
}
}
};
(別スレッドのダイアログ側でしたいこと)
ダイアログからの「選択結果」(例Yes or No)をセットする。
さて、どう書くか。本日のお題としておく。
回答は後ほど。
4(絶対)落ちないアプリ?
話はここで終わらない。というか、ここからが出発点
参考 絶対落ちないアプリの作り方
http://www.slideshare.net/fumihikoshiroyama/ss-47472394
非同期処理はコントローラよ り寿命が長いことがままある...Activityより長生き… ここにクラシュの罠がたくさんある
こちらが次のお題。