ハンドラーvs AsyncTask vsスレッド[終了]


382

私は少しの違いについて混乱してしまったHandlersAsyncTaskThreadsのAndroidインチ StackOverflowでかなりの数のブログと質問を読みました。

HandlerUIと通信するためのバックグラウンドスレッドです。たとえば、進行状況バーの更新はを介して行う必要がありますHandler。ハンドラーを使用すると、の利点が得MessagingQueuesられるため、メッセージをスケジュールしたり、複数のUI要素を更新したり、タスクを繰り返し実行したりする場合に役立ちます。

AsyncTaskは似ていますがHandler、実際にはを使用しますが、UIスレッドでは実行されないため、データのフェッチ(Webサービスのフェッチなど)に適しています。後でUIを操作できます。

Threadただし、UIと対話できず、より「基本的な」スレッドを提供し、のすべての抽象化を見逃しますAsyncTask

ただし、ソケット接続を実行したいのですが。これはハンドラーまたはスレッドで実行する必要がありAsyncTaskますか?UIの操作はまったく必要ありません。使用するパフォーマンスの点で違いはありますか?

一方、ドキュメントは大幅に改善されました。


1
チェックアウトする価値のあるもの:ダグラスシュミットがAndroidの同時実行性と同期を講義
Daniel F

9
「ハンドラーはバックグラウンドスレッドです」-上位投票された回答のいくつかもその方向に進んでいるようです。しかし、それは誤解です。A Handlerはスレッドではなく、何も実行しません。これは、あるスレッドから別のスレッドのメッセージキューにメッセージを安全に渡すための手段にすぎません。したがって、通常は(少なくとも)2つのスレッドを作成して、ハンドラーを使用できるようにする必要がありますが、ハンドラー自体は何も実行できません。
JimmyB 2015年

回答:


57

ハンドラーを使用したAndroidバックグラウンド処理のチュートリアルとして、VogellaサイトのAsyncTaskおよびローダーは次のように説明しています。

このHandlerクラスを使用してスレッドに登録でき、このスレッドにデータを送信するための単純なチャネルを提供します。

このAsyncTaskクラスは、バックグラウンドプロセスの作成とメインスレッドとの同期をカプセル化します。また、実行中のタスクの進行状況のレポートもサポートします。

また、a Threadは基本的にマルチスレッドのコア要素であり、開発者は次の欠点を抱えて使用できます。

Javaスレッドを使用する場合は、独自のコードで次の要件を処理する必要があります。

  • 結果をユーザーインターフェイスにポストバックした場合のメインスレッドとの同期
  • スレッドをキャンセルするためのデフォルトはありません
  • デフォルトのスレッドプーリングなし
  • Androidの構成変更を処理するためのデフォルトなし

そしてAsyncTaskAndroid Developer's Referenceがそれを置くように:

AsyncTaskUIスレッドを適切かつ簡単に使用できるようにします。このクラスを使用すると、スレッドやハンドラーを操作しなくても、UIスレッドでバックグラウンド操作を実行して結果を公開できます。

AsyncTask周りのヘルパークラスになるように設計されてThreadHandler して、一般的なスレッド化フレームワークを構成するものではありません。AsyncTasksは、理想的には短い操作(最大で数秒)に使用する必要があります。スレッドを長期間実行し続ける必要がある場合は、java.util.concurrentパッケージによって提供されるさまざまなAPIを使用することを強くお勧めします。エグゼキューター、ThreadPoolExecutor、FutureTask。

2015年5月更新:このトピックをカバーする一連の優れた講義を見つけました。

これはGoogle検索です:ダグラスシュミットレクチャーAndroidの同時実行と同期

これはYouTubeでの最初の講義のビデオです

これらはすべて、ヴァンダービルト大学CS 282(2013):Android向けシステムプログラミングの一部です。こちらがYouTubeプレイリストです

ダグラスシュミットは優れた講師のようです

重要:AsyncTaskスレッドの問題を解決するためにを使用することを検討している場合は、まず、おそらくより適切なプログラミングパターンを確認するReactiveX/RxAndroid必要があります。概要を得るための非常に優れたリソースは、例としてAndroid向けRxJava 2の学習です


4
:その講義シリーズでは、このリンクは右のいくつかのスレッドの例に行くことができますyoutu.be/4Vue_KuXfCk?t=19m24s
アグレッサー

353

ソースコードを見るAsyncTaskと、Handler純粋にJavaで記述されていることがわかります。(ただし、いくつかの例外があります。しかし、それは重要なポイントではありません)

つまり、AsyncTaskやには魔法はありませんHandler。これらのクラスにより、開発者としての生活が楽になります。

例:プログラムAがメソッドA()を呼び出す場合、メソッドA()はプログラムAを使用して別のスレッドで実行できます。次のコードで簡単に確認できます。

Thread t = Thread.currentThread();    
int id = t.getId();

一部のタスクに新しいスレッドを使用する必要があるのはなぜですか?あなたはそれをググることができます。多くの多くの理由、例えば:長時間の作業を大幅に持ち上げる。

だから、何の違いはThreadAsyncTaskHandler

AsyncTaskまたHandler、Javaで記述されているため(内部ではを使用しているためThread)、HandlerまたはAsyncTaskで実行できることはすべて、を使用してThreadも実現できます。

何をすることができますHandlerし、AsyncTask本当に役立ちますか?

最も明白な理由は、呼び出し側スレッドとワーカースレッド間の通信です。(呼び出し側スレッド:いくつかのタスクを実行するためにワーカースレッドを呼び出すスレッド。呼び出し側スレッドは必ずしもUIスレッドである必要はありません)。もちろん、他の方法で2つのスレッド間で通信できますが、スレッドの安全性のために多くの欠点(および危険)があります。

そのためHandler、およびを使用する必要がありAsyncTaskます。これらのクラスはほとんどの作業を行います。オーバーライドするメソッドを知るだけで済みます。

違いHandlerとは、AsyncTask次のとおりです。使用AsyncTask時に発信者のスレッドがあるUIスレッド。これはandroidドキュメントが言うことです:

AsyncTaskを使用すると、UIスレッドを適切かつ簡単に使用できます。このクラスを使用すると、スレッドやハンドラーを操作しなくても、UIスレッドでバックグラウンド操作を実行して結果を公開できます

2つのポイントを強調したいと思います。

1)UIスレッドの簡単な使用(したがって、呼び出し側スレッドがUIスレッドの場合に使用)。

2)ハンドラーを操作する必要はありません。(意味:AsyncTaskの代わりにハンドラーを使用できますが、AsyncTaskの方が簡単なオプションです)。

この投稿には、まだ触れていないことがたくさんあります。たとえば、UIスレッドとは何か、なぜ簡単なのか、などです。各クラスの背後にあるいくつかのメソッドを知って使用する必要があります。その理由は完全に理解できます。

@:Androidドキュメントを読むと、次のように表示されます。

ハンドラーを使用すると、スレッドのMessageQueueに関連付けられたMessageオブジェクトとRunnableオブジェクトを送信して処理できます

この説明は、最初は奇妙に思えるかもしれません。各スレッドには(to-doリストのような)各メッセージキューがあることを理解するだけでよく、スレッドは各メッセージを取得し、メッセージキューが空になるまでそれを実行します(作業を完了して就寝するのと同じように)。そうするときHandler通信するは、呼び出し側のスレッドにメッセージを表示するだけで、処理を待機します。

複雑ですか?Handler呼び出し側スレッドと安全に通信できることを覚えておいてください。


4
実際asynctaskもハンドラとfuturetaskに基づいており、参照
スミット

AsyncTaskは基本的に、ハンドラーとスレッドの上に構築されたヘルパークラスです。developer.android.com/reference/android/os/AsyncTask.html。「AsyncTaskはThreadとHandlerのヘルパークラスになるように設計されています」というドキュメントをご覧ください。AsyncTaskはAPI3でリリースされ、ハンドラーはAPI1以降に存在します。
hjchin 2016年

52

詳細に調べた後、それは簡単です。

AsyncTask

これは、Javaスレッドモデルについて何も知らなくてもスレッドを使用する簡単な方法です。 AsyncTaskワーカースレッドとメインスレッドに対応するさまざまなコールバックを提供します。

次のような小さな待機操作に使用します。

  1. Webサービスから一部のデータをフェッチし、レイアウトの上に表示します。
  2. データベースクエリ。
  3. 実行中の操作は決してネストされないことに気づいたとき。

Handler

Androidにアプリケーションをインストールすると、MAIN UI Threadと呼ばれるそのアプリケーションのスレッドが作成されます。すべてのアクティビティはそのスレッド内で実行されます。Androidシングルスレッドモデルルールでは、そのアクティビティ内で定義された別のスレッドのUI要素(ビットマップ、テキストビューなど)に直接アクセスすることはできません。

ハンドラーを使用すると、他のバックグラウンドスレッドからUIスレッドと通信できます。Androidは他のスレッドがUIスレッドと直接通信することを許可しないため、これはAndroidで役立ちます。ハンドラーは、スレッドのMessageQueueに関連付けられたMessageオブジェクトとRunnableオブジェクトを送信および処理できます。各Handlerインスタンスは、単一のスレッドとそのスレッドのメッセージキューに関連付けられています。新しいハンドラーが作成されると、それを作成しているスレッドのスレッド/メッセージキューにバインドされます。

次の場合に最適です。

  1. メッセージのキューイングを行うことができます。
  2. メッセージのスケジューリング。

Thread

スレッドについて話す時が来ました。

スレッドは、両方の親であるAsyncTaskHandler。どちらも内部的にスレッドを使用します。つまり、およびのような独自のスレッドモデルを作成することもできますが、そのためにはJavaのマルチスレッド実装について十分な知識が必要です。AsyncTaskHandler


1
AsyncTask APIは、実際には、Futures、Handlers、およびExecutorsで作成されています。:ソースコードを参照してくださいgrepcode.com/file_/repository.grepcode.com/java/ext/...
IgorGanapolsky

22

AsyncTaskいくつかの背景計算を行うと(オプションの進行状況の更新で)UIスレッドに結果を公開するために使用されます。UIに関心がないので、a HandlerまたはaのThread方が適切と思われます。

のメソッドThreadを使用して、バックグラウンドを生成し、メッセージをメインスレッドに戻す ことができます。Handlerpost


9

Androidは標準のJava スレッドをサポートしています。標準のスレッドとパッケージ「java.util.concurrent」のツールを使用して、アクションをバックグラウンドに配置できます。唯一の制限は、バックグラウンドプロセスからUIを直接更新できないことです。

バックグラウンドタスクからUIを更新する必要がある場合は、いくつかのAndroid固有のクラスを使用する必要があります。android.os.Handlerこれにはクラス「AsyncTask」またはクラス「」を使用できます

ハンドラ

クラス「Handler」はUIを更新できます。ハンドルは、メッセージを受信するためのメソッドと実行可能ファイルを提供します。ハンドラーを使用するには、ハンドラーをサブクラス化し、オーバーライドhandleMessage()してメッセージを処理する必要があります。を処理Runableするには、メソッドを使用できpost();ます。アクティビティにはハンドラーのインスタンスが1つだけ必要です。

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

AsyncTask

Activityコンテンツをダウンロードしたり、バックグラウンドで実行できる操作を実行したりする必要がある場合はAsyncTask、応答性の高いユーザーインターフェイスを維持し、それらの操作の進行状況をユーザーに公開できます。

詳細については、これらのリンクをご覧ください。

http://mobisys.in/blog/2012/01/android-threads-handlers-and-asynctask-tutorial/

http://www.slideshare.net/HoangNgoBuu/android-thread-handler-and-asynctask


6

Thread

ThreadUIスレッドに影響を与えることなく、長時間実行されるバックグラウンドタスクに新しいものを使用できます。Javaスレッドからは、UIスレッドを更新できません。

通常のThreadはAndroidアーキテクチャーにはあまり役に立たないため、スレッド化のためのヘルパークラスが導入されました。

スレッド化パフォーマンスのドキュメントページでクエリに対する回答を見つけることができます。

ハンドラー

AをHandler使用すると、メッセージとRunnableスレッドのに関連付けられたオブジェクトを送信および処理できますMessageQueue。各Handlerインスタンスは、単一のスレッドとそのスレッドのメッセージキューに関連付けられています。

の主な用途は2つありますHandler

  1. メッセージと実行可能ファイルを将来のある時点で実行されるようにスケジュールする。

  2. 自分のスレッドとは異なるスレッドで実行されるアクションをエンキューします。

AsyncTask

AsyncTaskUIスレッドを適切かつ簡単に使用できるようにします。このクラスを使用すると、スレッドやハンドラーを操作しなくても、UIスレッドでバックグラウンド操作を実行して結果を公開できます。

欠点:

  1. デフォルトでは、アプリAsyncTaskは作成したすべてのオブジェクトを1つのスレッドにプッシュします。したがって、それらはシリアル方式で実行され、メインスレッドと同様に、特に長い作業パケットがキューをブロックする可能性があります。このため、AsyncTaskを使用して、期間5ミリ秒未満の作業項目を処理します。

  2. AsyncTaskオブジェクトは、暗黙的な参照の問題の最も一般的な違反者でもあります。AsyncTaskオブジェクトには、明示的な参照に関連するリスクも存在します。

HandlerThread

長時間実行されるスレッドで作業ブロックを実行する従来のアプローチ(5msのワークロードに使用するAsyncTaskとは異なります)そのワークフローを手動で管理する機能が必要になる場合があります。ハンドラースレッドは、キューから作業を取得して処理する、長時間実行されるスレッドです。

ThreadPoolExecutor

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

ワークロードが多く、シングルHandlerThreadでは不十分な場合は、ThreadPoolExecutor

ただし、ソケット接続を実行したいのですが。これはハンドラまたはスレッド、あるいはAsyncTaskで実行する必要がありますか?UIの操作はまったく必要ありません。使用するパフォーマンスの点で違いはありますか?

UIの操作は必要ないため、を使用しない場合がありますAsyncTask。通常のスレッドはそれほど有用ではないためHandlerThread、最良のオプションです。ソケット接続を維持する必要があるため、メインスレッドのハンドラーはまったく役に立ちません。を作成し、のルーパーからHandlerThreadを取得します。HandlerHandlerThread

 HandlerThread handlerThread = new HandlerThread("SocketOperation");
 handlerThread.start();
 Handler requestHandler = new Handler(handlerThread.getLooper());
 requestHandler.post(myRunnable); // where myRunnable is your Runnable object. 

UIスレッドとやり取りしたい場合は、もう1つのハンドラーを使用して応答を処理できます。

final Handler responseHandler = new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            //txtView.setText((String) msg.obj);
            Toast.makeText(MainActivity.this,
                    "Foreground task is completed:"+(String)msg.obj,
                    Toast.LENGTH_LONG)
                    .show();
        }
    };

に、Runnable追加できます

responseHandler.sendMessage(msg);

実装の詳細については、こちらをご覧ください。

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


5

私の意見では、スレッドはソケット接続を行うための最も効率的な方法ではありませんが、実行中のスレッドに関してほとんどの機能を提供します。経験上、スレッドを長時間実行すると、デバイスが非常に高温になり、リソースを大量に消費するためです。シンプルなものでもwhile(true)数分で電話を加熱します。UIの相互作用は重要ではないと言う場合、おそらくAsyncTask、それらは長期的なプロセス用に設計されているため良いことです。これは私の意見です。

更新

私の上記の答えは無視してください!私は2011年にAndroidの経験が今よりはるかに少ないときにこの質問に答えました。上記の私の答えは誤解を招くものであり、間違っていると考えられています。多くの人々が私を訂正する下でそれについてコメントしたので、私はそれをそこに残します、そして私は私の教訓を学びました。

このスレッドにははるかに優れた他の答えがありますが、少なくとも私はより適切な答えを提供します。通常のJavaを使用しても問題はありませんThread。ただし、それを実装する方法には十分注意する必要があります。間違って実行すると、プロセッサに負荷がかかるためです(最も顕著な症状は、デバイスの温度上昇です)。AsyncTasksは、バックグラウンドで実行するほとんどのタスクに最適です(一般的な例は、ディスクI / O、ネットワーク呼び出し、データベース呼び出しです)。ただし、AsyncTasksは、ユーザーがアプリを閉じた後、またはデバイスをスタンバイにした後も継続する必要がある可能性のある特に長いプロセスには使用しないでください。ほとんどの場合、UIスレッドに属さないものはすべてで処理できますAsyncTask


おかげで、実際にAsyncTasksの代わりにスレッドを使用する必要がある理由はありますか?それともそれを利用する方がお勧めですか?
Alx

9
@AeroDroidあなたの例では、「単純なwhile(true)」では、ループにスリープ状態を追加しない限り、ここにCPUを固定します。これは、あらゆる無限ループに当てはまります。このオーバーヘッドが原因でCPUの使用量を減らしたい場合は、ループの最後に数ミリ秒間スレッドをスリープさせます。
エラー454

1
@エラー454-それは興味深いです!スリープ時間に適切な数値を選択する必要がある場合、それは40〜80ミリ秒の間ですか?
アビジット

6
@Abhijit私がSDLで行ったゲームのものから、ループに10 msのスリープを追加するだけで、アイドル状態の間に99%cpuから〜0に低下するのに十分でした。
エラー454

15
実際、developer.android.com / reference / android / os / AsyncTask.htmlは、「AsyncTasksは、理想的には、SHORT操作に使用する必要がある」と述べています。また、実行せずにシステムによって削除される可能性があるため、慎重に使用してください。
type-a1pha 2013

5

AsyncTaskバックグラウンドで実行される数秒以下の操作を実行するように設計されています(サーバーからのメガバイトのファイルのダウンロードや、ファイルIO操作などのCPUを集中的に使用するタスクには推奨されません)。実行時間の長い操作を実行する必要がある場合は、Javaネイティブスレッドを使用することを強くお勧めします。Javaは、スレッド関連のさまざまなクラスを提供して、必要な処理を実行します。HandlerUIスレッドを更新するために使用します。


2
public class RequestHandler {

    public String sendPostRequest(String requestURL,
                                  HashMap<String, String> postDataParams) {

        URL url;

        StringBuilder sb = new StringBuilder();
        try {
            url = new URL(requestURL);

            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(15000);
            conn.setConnectTimeout(15000);
            conn.setRequestMethod("POST");
            conn.setDoInput(true);
            conn.setDoOutput(true);


            OutputStream os = conn.getOutputStream();
            BufferedWriter writer = new BufferedWriter(
                    new OutputStreamWriter(os, "UTF-8"));
            writer.write(getPostDataString(postDataParams));

            writer.flush();
            writer.close();
            os.close();
            int responseCode = conn.getResponseCode();

            if (responseCode == HttpsURLConnection.HTTP_OK) {
                BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                sb = new StringBuilder();
                String response;
                while ((response = br.readLine()) != null){
                    sb.append(response);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return sb.toString();
    }

    private String getPostDataString(HashMap<String, String> params) throws UnsupportedEncodingException {
        StringBuilder result = new StringBuilder();
        boolean first = true;
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (first)
                first = false;
            else
                result.append("&");

            result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
            result.append("=");
            result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
        }

        return result.toString();
    }

}

1

ここで例を挙げて質問に答えてみましょう:)-MyImageSearch [メインアクティビティ画面の画像をここで参照してください-テキストの編集/検索ボタン/グリッドビューを含みます]

MyImageSearch

MyImageSearchの説明 - ユーザーが編集テキストフィールドに詳細を入力して検索ボタンをクリックすると、flickrが提供するWebサービスを介してインターネット上の画像が検索されます(キー/シークレットトークンを取得するには、そこに登録するだけです) -検索のために、HTTPリクエストとGET JSON Dataを送信して、グリッドビューをロードするために使用する個々の画像のURLを含むレスポンスを返します。

私の実装 - メインアクティビティで、AsyncTaskを拡張する内部クラスを定義して、doInBackGroundメソッドでHTTPリクエストを送信し、JSON応答をフェッチして、FlickrAdapterを介してGridViewを更新するために使用するFlickrItemsのローカルArrayListを更新します(BaseAdapterを拡張)、AsyncTaskのonPostExecute()でadapter.notifyDataSetChanged()を呼び出してグリッドビューを再読み込みします。ここでは、HTTPリクエストがブロッキング呼び出しであることに注意してください。これは、AsyncTaskを介して実行したためです。また、アイテムをアダプターにキャッシュして、パフォーマンスを向上させたり、SDカードに保存したりできます。FlickrAdapterで膨らませるグリッドには、実装にプログレスバーと画像ビューが含まれています。以下は、私が使用したmainActivityのコードです。

質問への回答 -個々の画像を取得するためのJSONデータを取得したら、ハンドラー、スレッド、またはAsyncTaskを介してバックグラウンドで画像を取得するロジックを実装できます。ここで、ダウンロードした画像はUI /メインスレッドに表示する必要があるため、コンテキストにアクセスできないため、スレッドをそのまま使用することはできません。FlickrAdapterで、私が考えることができる選択肢:

  • 選択肢1:LooperThread [スレッドを拡張する]を作成し、このスレッドを開いたままにすることで、1つのスレッドで連続して画像をダウンロードし続ける[looper.loop()]
  • 選択肢2:スレッドプールを利用し、myViewへの参照を含むmyHandlerを介してランナブルをポストしますが、グリッドビューのビューがリサイクルされるため、インデックス4のイメージがインデックス9に表示される場合にも問題が発生する可能性があります[ダウンロードはもっと時間がかかる]
  • 選択肢3 [これを使用しました]:スレッドプールを使用して、ImageViewのインデックスとImageView自体に関連するデータを含むメッセージをmyHandlerに送信します。したがって、handleMessage()を実行している間、currentIndexがダウンロードしようとした画像
  • 選択4:AsyncTaskを使用してバックグラウンドで画像をダウンロードしますが、ここでは、スレッドプールで必要なスレッドの数にアクセスできません。これは、Androidのバージョンによって異なりますが、選択3では意識的に決定できます使用されているデバイス構成に応じたスレッドプールのサイズ

ここにソースコード:

public class MainActivity extends ActionBarActivity {

    GridView imageGridView;
    ArrayList<FlickrItem> items = new ArrayList<FlickrItem>();
    FlickrAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageGridView = (GridView) findViewById(R.id.gridView1);
        adapter = new FlickrAdapter(this, items);
        imageGridView.setAdapter(adapter);
    }

    // To avoid a memory leak on configuration change making it a inner class
    class FlickrDownloader extends AsyncTask<Void, Void, Void> {



        @Override
        protected Void doInBackground(Void... params) {
            FlickrGetter getter = new FlickrGetter();

            ArrayList<FlickrItem> newItems = getter.fetchItems();

            // clear the existing array
            items.clear();

            // add the new items to the array
            items.addAll(newItems);

            // is this correct ? - Wrong rebuilding the list view and should not be done in background
            //adapter.notifyDataSetChanged();

            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);

            adapter.notifyDataSetChanged();
        }

    }

    public void search(View view) {
        // get the flickr data
        FlickrDownloader downloader = new FlickrDownloader();
        downloader.execute();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

私の回答が長くなることで、細かい部分の理解に役立つことを願っています。


類推のための例に基づいた私の説明が反対票が投じられた理由を知っていてもいいので、それから私もそれから学ぶことができますか?
akshaymani 2014

2
このトピックは少し古いですが、コアコンセプトはまだ最新のままです。私の最初の質問はまったく答えられていません。例を挙げて、それがどのように機能するかを説明していますが、質問ではハンドラー、asynctask、スレッドの違いを求めています。
Alx

@ 80leaves okポイントを取得しました。他の方法を選択するという結論に至った方法について説明してみました。とにかく、私が書いたものが正しいかどうか、またはさらに改善できるかどうかについて、あなたや他の人の意見を聞きたいです。
akshaymani 2014

1

どちらを選択するかは要件に依存します

ハンドラは、主に他のスレッドからメインスレッドに切り替えるために使用されます。ハンドラーは、実行可能なタスクをキューにポストするルーパーに接続されます。だからあなたがすでに他のスレッドにいてメインスレッドに切り替えるなら、非同期タスクや他のスレッドの代わりにハンドルが必要です

ルーパーではないメインスレッド以外で作成されたハンドラーがハンドルを作成したときにエラーが発生しない場合は、そのスレッドをロッパーにする必要があります。

AsyncTaskは、バックグラウンドスレッドで実行され、メインスレッド**にその結果が得られる数秒間のコードを実行するために使用される* AsyncTask制限事項 1.非同期タスクは、アクティビティのライフサイクルに接続されていないと、その活性は、ローダのdoesnのに対し、破壊された場合でも、それが実行し続けますこの制限はありません。2.すべての非同期タスクは、実行のために同じバックグラウンドスレッドを共有しますが、これもアプリのパフォーマンスに影響します

スレッドは、バックグラウンド作業のためにもアプリで使用されますが、メインスレッドでのコールバックはありません。要件が1つのスレッドではなくいくつかのスレッドに適しており、タスクを何度も実行する必要がある場合は、スレッドプールエグゼキュータの方が適切なオプションです。


0

アプリを起動すると、コードを実行するプロセスが作成されます。コンピューティングリソースを効率的に使用するために、プロセス内でスレッドを開始して、一度に複数のタスクを実行できます。したがって、スレッドを使用すると、アイドル時間なしでcpuを効率的に使用して、効率的なアプリを構築できます。

Androidでは、すべてのコンポーネントが単一の呼び出されたメインスレッドで実行されます。Androidシステムはタスクをキューに入れ、メインスレッドで1つずつ実行します。実行時間の長いタスクを実行すると、アプリが応答しなくなります。

これを防ぐには、ワーカースレッドを作成して、バックグラウンドタスクまたは長時間実行タスクを実行します。

ハンドラ

Androidはシングルスレッドモデルを使用するため、UIコンポーネントは非スレッドセーフで作成されます。つまり、作成されたスレッドのみがそれらにアクセスする必要があります。つまり、UIコンポーネントはメインスレッドでのみ更新する必要があります。UIコンポーネントはメインスレッドで実行されるため、ワーカースレッドで実行されるタスクはUIコンポーネントを変更できません。ここで、ハンドラーが登場します。ハンドラーは、ルーパーの助けを借りて、新しいスレッドまたは既存のスレッドに接続し、接続されたスレッドに含まれるコードを実行できます。

ハンドラーは、スレッド間通信を可能にします。ハンドラーを使用すると、バックグラウンドスレッドが結果を送信でき、メインスレッドに接続されているハンドラーがメインスレッドのUIコンポーネントを更新できます。

AsyncTask

androidが提供するAsyncTaskは、スレッドとハンドラーの両方を使用して、バックグラウンドで単純なタスクを実行し、バックグラウンドスレッドからメインスレッドに結果を簡単に更新します。

例については、androidスレッド、ハンドラー、asynctask、スレッドプールをご覧ください。


-1

Handler-スレッド間の通信媒体です。Androidでは、ハンドラを介してメッセージを作成および送信することにより、メインスレッドとの通信に主に使用されます

AsyncTask-バックグラウンドスレッドで長時間実行されるアプリケーションを実行するために使用されます。n AsyncTaskを使用すると、バックグラウンドスレッドで操作を実行し、アプリケーションのメインスレッドで結果を取得できます。

Thread-同時実行性と最大CPU使用率を達成するための軽量プロセスです。Androidでは、スレッドを使用して、アプリのUIに触れないアクティビティを実行できます

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.