Android:いつHandler()を使用し、いつスレッドを使用する必要がありますか?


129

長期実行タスクやネットワークを使用するロジックなど、非同期で実行する必要がある場合、または何らかの理由で、新しいスレッドを開始して実行すると正常に動作します。ハンドラーを作成して実行することもできます。違いは何ですか?それぞれをいつ使用すればよいですか?a ではなくa を使用する利点/理由は何ですか?HandlerThread

PS。-この質問のために、無視しましょうAsyncTask。- Handler().postDelayed使用例は私には明らかです。この質問のために、タスクをすぐに開始する必要があると仮定しましょう。


あなたの状況では、まっすぐ進んで新しいスレッドを使用してください、私の次の提案はAsyncTaskですが、それはあなたが明確に望んでいるものではありません。ハンドラーは主に、実行可能ファイルに遅延やその他の種類のカスタマイズを追加する場合に使用されます。
kabuto178

1
@ kabuto178まあ、あなたがスキップしたことを言及する価値のあるハンドラーの他の利点があります。このような...別のスレッドからUIスレッドとやり取りすることができること、など
tony9099

回答:


168

あなたがやっていることが「重い」場合は、スレッドで行う必要があります。独自のスレッドで明示的に開始しない場合、メイン(UI)スレッドで実行されます。これは、ユーザーによるジッターの応答やインターフェースの応答が遅いことがわかる場合があります。

興味深いことに、スレッドを使用している場合は、開始しているワークスレッドとメインスレッド間の通信手段としてHandlerも使用すると便利なことがよくあります。

典型的なスレッド/ハンドラーの相互作用は次のようになります。

Handler h = new Handler(){
    @Override
    public void handleMessage(Message msg){
        if(msg.what == 0){
            updateUI();
        }else{
            showErrorDialog();
        }
    }
};

Thread t = new Thread() {
    @Override
    public void run(){
        doSomeWork();
        if(succeed){
            //we can't update the UI from here so we'll signal our handler and it will do it for us.
            h.sendEmptyMessage(0);
        }else{
            h.sendEmptyMessage(1);
        }
    }   
};

ただし、一般的には、実行時間が長くなるか、非常に集中的になる可能性のある作業(ネットワーク、ファイルIO、重い演算など)を実行するときは、必ずスレッドを使用する必要があります。


迅速な返信と投資時間(および返信のスピード!!)をありがとう!それで、これが得られたかどうかを見てみましょう:ハンドラーは、ワーカースレッドとUIスレッド間の非ブロック通信を容易にするように設計されていますか?
JRun、

3
@JRunこれは用途の1つです。それに関するいくつかの優れた情報については、Javaドキュメントのハンドラの説明を確認してください。別の使用法を含める(将来のある時点で実行されるメッセージと実行可能ファイルをスケジュールするため)。
FoamyGuy

@FoamyGuyをうまく説明しました!
tony9099 2013年

こんにちは、は(新しいビューがロードされたupdateUI()onCreateView)に実行されることが保証されていますか?
Zyoo

1
なんでmessage.what()?それだけではないif(msg == 0){ですか?本当にありがとう!:)
Ruchir Baronia

64

ハンドラとスレッドは実際には2つの異なるものです。

実行時間の長いジョブを実行するには、スレッドを作成する必要があります。

ハンドラーは、2つのスレッド間で通信するのに非常に便利なオブジェクトです(たとえば、バックグラウンドスレッドはUIを更新する必要があります。ハンドラーを使用して、バックグラウンドスレッドからUIスレッドにいくつかのRunnableをポストできます)。

したがって、ハンドラとスレッドのどちらかを選択することはできません。スレッドを使用して重い仕事をしてください!(バックグラウンドスレッドが何らかのジョブを別のスレッドで実行するようトリガーする場合は、ほとんどの場合UIスレッドでハンドラーを使用できます)


迅速な返信と投資時間(および返信のスピード!!)をありがとう!
JRun、

28

HandlerThread2つの異なるものですが、互いに矛盾しません。a Handlerとa Threadを同時に使用でき、実際にはそれぞれHandlerがで実行されている必要がありますThread

詳しくは、こちらの記事をご覧ください。

ここに画像の説明を入力してください


19

Handler同じ上で実行されThreadThread別のスレッドで実行されます。

同じスレッド(通常はGUI要素など)で何かを実行する必要がある場合は、ハンドラーを使用します

メインスレッドを他のことをするために自由にしたい場合は、スレッドを使用します。これは、かなり時間がかかるものに使用します。


6
同じスレッドで何かを実行したい場合、なぜハンドラーを使用する必要があるのですか?mHandler.post(...)メソッドの目的は何ですか?
エリアス

1
エリアス、そのような場合、特定の時間の後に特定のタスクを実行したい場合、またはX時間ごとにタスクを繰り返す場合は、ハンドラーを使用できます。あなたがこれらのものを使いたくないなら、あなたは正しいです。ハンドラを使用することは価値がありません。ハンドラーはそれが作成されたスレッド上で実行されるため、GUIの処理をすぐに実行でき、その後、UIスレッドでbcozを実行できます。
tony9099 2013年

14

ハンドラーは、バックグラウンドとUIスレッド間の通信の最良の方法です。通常、ハンドラーはスレッドのメッセージキューに関連付けられており、メッセージを送信するために使用され、メッセージに実行可能です。

使用する:

スレッド: UIスレッドよりもsaperate(Background)スレッドでタスクを実行します。(UIスレッドのブロックを解除するのに役立ちます)

ハンドラー UIとバックグラウンドスレッド間の通信に使用されます。

この記事をご覧ください


4

新しいスレッドからユーザーインターフェイスを更新する必要がある場合は、ユーザーインターフェイススレッドと同期する必要があります。

これにはandroid.os.HandlerクラスまたはAsyncTasksクラスを使用できます。

Handlerクラスはユーザーインターフェイスを更新できます。ハンドラーは、メッセージまたはRunnableクラスのインスタンスを受信するためのメソッドを提供します。

スレッドは、sendMessage(Message msg)メソッドまたはsendEmptyMessage()メソッドを使用してメッセージを投稿できます。

... スレッドなどに関する詳細はこちら(さまざまなスレッド化および同期メカニズムのturorialsと、いつ何を使用するかを含む)


私の質問に答えてくれてありがとう。私はLars Vogelのブログが大好きです。非常に洞察に富み、簡単にフォローできます。ありがとう!
JRun、

2

スレッドではなくハンドラを使用する利点/理由は何ですか?

A ハンドラは、あなたがメッセージと送信して処理することを可能にするRunnableスレッドのに関連付けられているオブジェクトをMessageQueue。各Handlerインスタンスは、単一のスレッドとそのスレッドのメッセージキューに関連付けられています。

新しいを作成するとHandler、それは、それを作成しているスレッドのスレッド/メッセージキューにバインドされます。その時点から、メッセージと実行可能ファイルはそのメッセージキューに配信され、メッセージキューから出たときに実行されます。 。

ハンドラーの主な用途は2つあります。

  1. メッセージとRunnableが将来のある時点で実行されるようにスケジュールする
  2. 自分のスレッドとは異なるスレッドで実行されるアクションをエンキューします。

Javaスレッドを使用する場合は、メインスレッドとの同期、スレッドのキャンセルなど、自分で何かを処理する必要があります。

ThreadPoolExecutorまたはExecutorServiceAPI を使用しない限り、この単一のスレッドはスレッドプールを作成しません。

(Blackbeltの回答に関するコメントからこのクエリを取得してください)

エグゼキューターを使用しないのはなぜですか?それを行うためにハンドラーを使用したいと思ったとしても、どうやって?

参照:スレッドパフォーマンスの記事

高度な並列分散タスクに削減できる特定のタイプの作業があります。作業パケットの膨大な量では、これが作成し、AsyncTaskそしてHandlerThread適切なクラスではありません。のシングルスレッドの性質は、スレッドAsyncTaskプールされたすべての作業を線形システムに変えます。HandlerThread一方、クラスを使用すると、プログラマーはスレッドのグループ間の負荷分散を手動で管理する必要があります。

ThreadPoolExecutorは、このプロセスを簡単にするためのヘルパークラスです。このクラスは、スレッドのグループの作成を管理し、それらの優先順位を設定し、作業がそれらのスレッド間でどのように分散されるかを管理します。ワークロードが増加または減少すると、クラスはワークロードに適応するためにより多くのスレッドをスピンアップまたは破棄します。

 BlockingQueue workQueue= new LinkedBlockingQueue<Runnable>(100); // Work pool size
 ThreadPoolExecutor executor = new ThreadPoolExecutor(
            Runtime.getRuntime().availableProcessors(),       // Initial pool size
            Runtime.getRuntime().availableProcessors(),       // Max pool size
            1, // KEEP_ALIVE_TIME
            TimeUnit.SECONDS, //  KEEP_ALIVE_TIME_UNIT
            workQueue);

詳細については、create-threadpoolに関するこの開発者ガイドの記事を参照してください。

Handler複数のRunnableインスタンスを実行するための使用法については、この投稿をご覧ください。この場合、すべてのRunnableタスクは単一のスレッドで実行されます。

Android:スレッドでのトースト


1

Handlerと組み合わせて使用​​してThread、Queuedメカニズムを作成できます。Uouはにhandler何かを投稿するために使用できますThread Looper


私の質問に答えてくれてありがとう。エグゼキューターを使用しないのはなぜですか?それを行うためにハンドラーを使用したいと思ったとしても、どうやって?
JRun、

executorは少し異なります。これを使用するには、スレッドを拡張し、実行時にLooperクラスのstatic.metohd prepare.ofを呼び出す必要があります。静的メソッドループを呼び出した後、キューが作成され、ハンドラービンの順序を使用して要求を転送し、結果を取得できます
Blackbelt
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.