LoginSignup
9
9

More than 5 years have passed since last update.

(メモ書き)AndroidのHandlerとHandlerThreadで情報の同期

Last updated at Posted at 2016-10-20

古くからある、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より長生き… ここにクラシュの罠がたくさんある

こちらが次のお題。

9
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
9