32

我有 2 个 ASyncTask,一个从 httpPost 检索值,另一个更新 UI 的一些元素(包括列表视图)。问题在于,由于两个 ASyncTask 共享相同的后台线程,如果网络操作首先启动并且运行缓慢(由于网络连接不良)。其他后台线程花费太多时间使应用程序不负责任。

由于两个 ASyncTask 都是独立的,因此让另一个等待是非常愚蠢的。不同的类使用不同的线程会更符合逻辑,我错了吗?

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

}
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为您的Task1Task2。基本上 AsyncTask 的变化出现在 Honeycomb 中(请参阅“执行顺序”部分中的 Android SDK 文档),因此在之前,您像往常一样启动它,对于 HC 及更高版本,executeOnExecutor()如果您不喜欢新行为(没有人喜欢,我思考)

于 2012-08-28T23:04:46.167 回答
8

一种更通用的方法是将两个辅助方法放在一个实用程序类中,如下所示:

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)or执行任务Utils.execute(mytask, params),它会负责并行执行它们。

于 2012-08-29T02:33:13.740 回答
1

问题是每个 AsyncTask 都在同一个 ThreadPoolExecutor 中运行,该 ThreadPoolExecutor 被编码到 API 中。这个 ThreadPoolExecutor 可以根据你的 Android 版本创建不同数量的 WorkerThread。我不记得版本号,但想法是在较旧的 Android 版本中它是 1 个 WorkerThread。然后在以后的版本中更新为 5。最近又回到了1。这就是您的 AsyncTasks 被阻止的原因。它们都在同一个 WorkerThread 上运行,因此它们是按顺序执行的。尝试使用带有 THREAD_POOL_EXECUTOR 的 executeOnExecutor 来实现真正的并行执行。但是,您只能从 API 11 开始使用它。

于 2013-07-13T14:14:09.530 回答