1. ホーム
  2. スクリプト・コラム
  3. その他

[解決済み】Looper.prepare()を呼び出していないスレッド内でハンドラを作成できない。)

2022-01-10 20:49:19

質問

は以下のようなコードです。

Toast toast = Toast.makeText(mContext, "Something", Toast.LENGTH_SHORT);

実行すると、エラーが発生します。

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
     at android.os.Handler.<init>(Handler.java:121)
     at android.widget.Toast.<init>(Toast.java:68)
     at android.widget.Toast.makeText(Toast.java:231)

解決方法は?

ワーカスレッドから呼び出している。を呼び出す必要があります。 Toast.makeText() (そしてUIを扱う他のほとんどの関数も) メインスレッド内から行います。例えば、ハンドラを使うことができます。

調べる UIスレッドとの通信 のドキュメントを参照してください。簡単に説明すると

// Set this up in the UI thread.

mHandler = new Handler(Looper.getMainLooper()) {
    @Override
    public void handleMessage(Message message) {
        // This is where you do your work in the UI thread.
        // Your worker tells you in the message what to do.
    }
};

void workerThread() {
    // And this is how you call it from the worker thread:
    Message message = mHandler.obtainMessage(command, parameter);
    message.sendToTarget();
}

その他のオプション

を使うことができます。 Activity.runOnUiThread() . を使えば簡単です。 Activity :

@WorkerThread
void workerThread() {
    myActivity.runOnUiThread(() -> {
        // This is where your UI code goes.
    }
}

また、メインのルーパーに投稿することもできます。これは Context .

@WorkerThread
void workerThread() {
    ContextCompat.getMainExecutor(context).execute(()  -> {
        // This is where your UI code goes.
    }
}

非推奨。

を使用することができます。 AsyncTask これは、バックグラウンドで実行されるほとんどのものに対してうまく機能します。このフックには、進行状況や完了を示すために呼び出すことができるものがあります。

便利ですが、正しく使用しないとコンテキストをリークする可能性があります。公式に非推奨とされているので、もう使わない方がいい。