32

2つのASyncTasksがあります。1つはhttpPostから値を取得し、もう1つはUIのいくつかの要素(リストビューを含む)を更新します。問題は、両方のASyncTasksが同じバックグラウンドスレッドを共有しているため、ネットワーク操作が最初に開始され、実行速度が遅くなる場合(ネットワーク接続が悪いため)です。他のバックグラウンドスレッドは時間がかかりすぎて、アプリを無責任にします。

両方のASyncTasksは独立しているので、一方をもう一方を待たせるのはかなり愚かです。異なるクラスが異なるスレッドを使用するのは、より論理的な非同期タスクになるでしょう、私は間違っていますか?

ASyncTaskドキュメントを読んでいます。executeOnExecutor()の使用について 説明していますが、11未満のAPIレベルでそれを解決するにはどうすればよいですか?

ここに「問題」を再現する小さな例があります

        new Task1().execute();
        new Task2().execute();

public class Task1 extends AsyncTask<Void, Void, Void> {

    @Override
    protected Void doInBackground(Void... params) {
        GLog.e("doInBackground start 1");
        SystemClock.sleep(9000);
        GLog.e("doInBackground end 1");
        return null;
    }

    @Override
    protected void onPreExecute() {
        GLog.e("onPreExecute 1");
        super.onPreExecute();
    }

    @Override
    protected void onPostExecute(Void result) {
        GLog.e("onPostExecute 1");
        super.onPostExecute(result);
    }

}

public class Task2 extends AsyncTask<Void, Void, Void> {

    @Override
    protected void onPreExecute() {
        GLog.e("onPreExecute 2");
        super.onPreExecute();
    }

    @Override
    protected Void doInBackground(Void... params) {
        GLog.e("doInBackground start 2");
        SystemClock.sleep(9000);
        GLog.e("doInBackground end 2");
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        GLog.e("onPostExecute 2");
        super.onPostExecute(result);
    }

}
4

3 に答える 3

52

これが私のコードでこれを処理する方法です:

if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ) {
    new MyAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} else {
    new MyAsyncTask().execute();
}

そして、それぞれMyAsyncTaskあなたのものと交換してください。基本的に、AsyncTaskの変更はHoneycombに表示されます(「実行の順序」セクションのAndroid SDKドキュメントを参照)。その前に、通常どおりに起動します。HC以上の場合は、新しい動作が気に入らない場合に使用します(誰もしません、私は考える)Task1Task2executeOnExecutor()

于 2012-08-28T23:04:46.167 に答える
8

これを行うもう少し一般的な方法は、次のように2つのヘルパーメソッドをユーティリティクラスに配置することです。

class Utils {

    @SuppressLint("NewApi")
    public static <P, T extends AsyncTask<P, ?, ?>> void execute(T task, P... params) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
        } else {
            task.execute(params);
        }
    }
}

次に、Utils.execute(mytask)またはUtils.execute(mytask, params)を使用してタスクを実行でき、それらを並行して実行します。

于 2012-08-29T02:33:13.740 に答える
1

問題は、すべてのAsyncTaskがAPIにコード化されている同じThreadPoolExecutorで実行されることです。このThreadPoolExecutorは、Androidのバージョンに応じて異なる数のWorkerThreadを作成できます。バージョンの数は覚えていませんが、古いAndroidバージョンでは1つのWorkerThreadでした。その後、それ以降のバージョンでは5に更新されました。そして最近、再び1に戻りました。これが、AsyncTasksがブロックされる理由です。これらはすべて同じWorkerThreadで実行されるため、順番に実行されます。真の並列実行を実現するには、THREAD_POOL_EXECUTORとともにexecuteOnExecutorを使用してみてください。ただし、これはAPI11以降でのみ使用できます。

于 2013-07-13T14:14:09.530 に答える