Подтвердить что ты не робот

ASyncTasks блокирует другие

У меня есть 2 ASyncTasks, один извлекает значение из httpPost, а другое обновляет некоторые элементы пользовательского интерфейса (включая список). Проблема заключается в том, что, поскольку оба ASyncTasks используют один и тот же фоновый поток, если сетевое взаимодействие запускается первым и работает медленно (из-за плохой сетевой связи). Другие фоновые потоки занимают слишком много времени, делая приложение безответственным.

Поскольку обе ASyncTasks являются независимыми, это довольно глупо, чтобы подождать другого. Было бы логичнее, если бы асинтемы разных классов использовали разные потоки, я не прав?

Чтение документа ASyncTask. Переговоры об использовании executeOnExecutor(), но как я могу решить это на уровне API ниже 11?

Вот небольшой пример, который воспроизводит "проблему"

        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);
    }

}
4b9b3361

Ответ 1

Вот как я обрабатываю это в своем коде:

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

И замените MyAsyncTask вашими Task1 и Task2 соответственно. В основном изменение AsyncTask появилось в Honeycomb (см. Раздел "SDK docs здесь в разделе" Порядок выполнения"), поэтому до этого вы запускаете его как обычно, для HC и up, используйте executeOnExecutor(), если вам не нравится новое поведение (кажется, никто)

Ответ 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), и он будет выполнять параллельное выполнение.

Ответ 3

Проблема заключается в том, что каждый AsyncTask работает в том же ThreadPoolExecutor, который закодирован в API. Этот ThreadPoolExecutor может создать другое количество WorkerThread в зависимости от вашей версии Android. Я не помню номера версий, но идея в том, что в старых версиях Android это был 1 WorkerThread. Затем он был обновлен до 5 в более поздних версиях. А недавно снова вернулся к 1. Вот почему ваши AsyncTasks заблокированы. Они запускают все на одном WorkerThread, и поэтому они выполняются последовательно. Попробуйте использовать executeOnExecutor с THREAD_POOL_EXECUTOR для достижения правильного параллельного выполнения. Однако вы можете использовать это только с API 11.