1. ホーム
  2. Android

スレッド内にハンドラを作成できない Looper.prepare() を呼び出していないスレッド

2022-02-10 13:12:36

 8月9日にも、サービスでのサブスレッド作成時

RuntimeException: Looper.prepare() を呼び出していないスレッド Thread 内でハンドラを作成できない。

問題です。コードは以下の通りです。

new Thread(new Runnable() {
                @Override
                public void run() {
                    timer = new Timer(mTotalTime, TimeSetted.SECOND_TO_MILL);
                    timer.start();
                    Log.d(TAG,"Countdown start");
                }
            }).start();

 に変更します。

new Thread(new Runnable() {
                @Override
                public void run() {
                    Looper.perpare();//add part
                    timer = new Timer(mTotalTime, TimeSetted.SECOND_TO_MILL);
                    timer.start();
                    Log.d(TAG,"Countdown start");
                    Looper.loop();//add part
                }
            }).start();

この後、アプリは普通に実行されます。つまり、具象ロジックの前後にLooper.perpare()とLooper.loop()のメソッドを追加しています。

  エラーの原因を調べてみると、メインスレッド以外ではLooperが開いておらず、HandlerオブジェクトをLooperオブジェクトにバインドする必要があり、スレッドのメッセージループを作成するためにLooper.prepare()を呼び出し、メッセージループを動作させるためにLooper.loop()を呼び出すことが必要。

ここで問題です。

  このサブスレッドにも、前のdoInBackgroundにも新しいハンドラは存在しないのに、なぜこのエラーが発生するのでしょうか?

  使用しているCountdownTimerのソースコードを見たところ、start(),pause(),cancel()メソッドがメッセージとハンドラで実装されていて、サブスレッドでCountdownTimerを使用すると、デフォルトではLooperがバインドされていないのでエラーが発生するようです。

結論

  1. スレッド内にハンドラを作成できない Looper.prepare()を呼んでいないスレッドは、通常、子スレッドでLooperがバインドされていないハンドラを使用している場合に発生する。ハンドラ文の前後にLooper.prepare()とLooper.loop()メソッドを追加するだけだ。

2 . 子スレッドを作成し、新しいハンドラオブジェクトを使用せずにAsyncTaskのdoInBackgroundを使用した場合、通常このエラーは発生しません。他のメソッドを呼び出すときにハンドラを使用することによるエラーを報告しています。