487

UIスレッドでコードを実行するという観点では、次の間に違いはありますか?

MainActivity.this.runOnUiThread(new Runnable() {
    public void run() {
        Log.d("UI thread", "I am the UI thread");
    }
});

また

MainActivity.this.myView.post(new Runnable() {
    public void run() {
        Log.d("UI thread", "I am the UI thread");
    }
});

private class BackgroundTask extends AsyncTask<String, Void, Bitmap> {
    protected void onPostExecute(Bitmap result) {
        Log.d("UI thread", "I am the UI thread");
    }
}
4

8 に答える 8

309

それらのどれも正確に同じではありませんが、それらはすべて同じ正味の効果を持ちます。

最初のスレッドと2番目のスレッドの違いは、コードの実行時にメインアプリケーションスレッドを使用している場合、最初のスレッド(runOnUiThread()Runnableすぐに実行されることです。2番目の( )は、すでにメインアプリケーションスレッドを使用している場合でも、post()常にイベントキューの最後にを置きます。Runnable

3つ目は、のインスタンスを作成して実行すると仮定するとBackgroundTask、スレッドプールからスレッドを取得して、デフォルトのno-opを実行するために多くの時間を浪費してから、doInBackground()最終的にはになりpost()ます。これは、3つの中で最も効率が悪いです。の使用AsyncTaskだけでなく、バ​​ックグラウンドスレッドで実際に行う作業がある場合に使用しますonPostExecute()

于 2012-10-11T23:33:44.123 に答える
281

私はHPPコメントからのものが好きです、それはパラメータなしでどこでも使用することができます:

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        Log.d("UI thread", "I am the UI thread");
    }
});
于 2014-08-11T19:01:03.300 に答える
64

使用する4番目の方法がありますHandler

new Handler().post(new Runnable() {
    @Override
    public void run() {
        // Code here will run in UI thread
    }
});
于 2012-10-11T23:36:59.190 に答える
18

Pomberの答えは受け入れられますが、私は新しいオブジェクトを繰り返し作成することはあまり好きではありません。最善の解決策は、常にメモリの占有を軽減しようとするものです。はい、自動ガベージコレクションがありますが、モバイルデバイスのメモリ節約はベストプラクティスの範囲内にあります。以下のコードは、サービスのTextViewを更新します。

TextViewUpdater textViewUpdater = new TextViewUpdater();
Handler textViewUpdaterHandler = new Handler(Looper.getMainLooper());
private class TextViewUpdater implements Runnable{
    private String txt;
    @Override
    public void run() {
        searchResultTextView.setText(txt);
    }
    public void setText(String txt){
        this.txt = txt;
    }

}

次のような場所から使用できます。

textViewUpdater.setText("Hello");
        textViewUpdaterHandler.post(textViewUpdater);
于 2015-01-05T09:24:54.150 に答える
13

Android Pの時点で、次のものを使用できますgetMainExecutor()

getMainExecutor().execute(new Runnable() {
  @Override public void run() {
    // Code will run on the main thread
  }
});

Android開発者向けドキュメントから:

このコンテキストに関連付けられたメインスレッドでキューに入れられたタスクを実行するエグゼキュータを返します。これは、アプリケーションコンポーネント(アクティビティ、サービスなど)に呼び出しをディスパッチするために使用されるスレッドです。

CommonsBlogから:

ContextでgetMainExecutor()を呼び出して、メインアプリケーションスレッドでジョブを実行するExecutorを取得できます。LooperとカスタムExecutor実装を使用してこれを実現する方法は他にもありますが、これはより簡単です。

于 2018-03-09T03:54:48.497 に答える
12

フラグメントで使用する必要がある場合は、を使用する必要があります

private Context context;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        this.context = context;
    }


    ((MainActivity)context).runOnUiThread(new Runnable() {
        public void run() {
            Log.d("UI thread", "I am the UI thread");
        }
    });

それ以外の

getActivity().runOnUiThread(new Runnable() {
    public void run() {
        Log.d("UI thread", "I am the UI thread");
    }
});

ページャーフラグメントなどの状況ではnullポインタ例外が発生するため

于 2018-04-28T14:32:10.443 に答える
5

ハンドラーを使用する

new Handler(Looper.getMainLooper()).post(new Runnable() {
    @Override
    public void run() {
        // Code here will run in UI thread
    }
});
于 2018-06-01T04:50:25.057 に答える
0

Kotlinバージョン:

Handler(Looper.getMainLooper()).post {
   Toast.makeText(context, "Running on UI(Main) thread.", Toast.LENGTH_LONG).show()
}

または、Kotlinコルーチンを使用している場合:コルーチンスコープ内に次を追加します:

withContext(Dispatchers.Main) {
   Toast.makeText(context, "Running on UI(Main) thread.", Toast.LENGTH_LONG).show()
}
于 2021-12-08T13:35:04.307 に答える