什么时候在Android中使用AsyncTask,什么时候使用Thread

6

在后台处理工作并且可以通过一些机制来操作UI线程的情况下,何时使用AsyncTask和何时使用Thread


当您在运行任务并行时没有问题,对于相同的事情,即说您想要处理不同的计算,您只需在一个线程中启动它。对于asyncTask,当您需要从后台工作返回某些内容,或者希望在执行某些其他进程或更新某些视图等之前等待某些进程完成时。 - Saqib
3
类似的问题已有回答:https://dev59.com/MmMl5IYBdhLWcg3wV10F - greenmarker
我的要求是访问一个服务,然后检索一些数据并将对象列表保存在列表中,同时更新其进度的 UI。检索可能需要一些时间。 - user3048027
3个回答

4

希望这能帮到你:

对于长时间运行的任务,我们使用Java线程和Android本地的AsyncTask。

基本上,使用AsyncTask来处理:

  • 不需要下载大量数据的简单网络操作
  • 可能需要花费几毫秒以上的磁盘绑定任务

并且使用Java线程来处理:

  • 涉及中等到大量数据(上传或下载)的网络操作
  • 需要在后台运行的高CPU任务
  • 任何您想要相对于GUI线程控制CPU使用率的任务

有关更多信息,请参见Mohit的回答点击此处

编辑:

服务类似于Activity,但没有界面。如果您想要获取天气,例如,您不会为其创建一个空白活动,而是将使用服务。服务可以访问Context对象,该对象具有独立的生命周期。这允许许多活动重用公共代码,并且在公共或公开服务的情况下,在许多应用程序中使用。
默认情况下,服务在调用组件进程的主线程上运行(因此可能会降低响应性并导致ANR),因此您应该创建一个新线程来执行长时间运行的操作。

线程是一条线程,可能您已经从其他部分了解过它。您需要知道的是,您无法从线程中更新UI。您需要使用Handler进行此操作,并且有时停止线程也会变得棘手。线程是一种在不阻塞其他工作的情况下完成工作的机制...

服务不意味着线程,线程也不意味着服务。两者是不同的。

AsyncTask是建议使用的智能线程。智能,因为它可以帮助处理方法,而且有两个在UI线程上运行的方法,这对于更新UI组件很有用。


我会完全放弃Thread类,转而使用“新”的Executor框架+Runnable/Callable+Future。 - ElDuderino

1
AsyncTask是Android SDK提供的一种辅助类,旨在使在后台任务完成后更容易跳转到UI线程。它基于标准的Java线程API构建,不提供任何仅能通过线程实现的功能。它解决了在短时间内切换后台线程和UI线程的常见情况。
通常在必须在后台任务完成后“回到”UI线程或在任务执行期间向UI线程提供反馈时,使用AsyncTask很方便。否则,它只是额外负担。
您不必强制使用AsyncTask。如果您作为开发人员更喜欢直接使用Thread或Future,则可以使用它并在后台任务完成后手动跳转到UI线程。
编辑:
一些其他答案建议使用AsyncTask应该限制在短任务上。据说是因为它使用了一个公共池。然而,这已经不再是真实情况,自API Level 11(也就是很长时间以来)以来。您可以使用executeOnExecutor代替execute在专用线程池中执行AsyncTask。请参见http://developer.android.com/reference/android/os/AsyncTask.html#executeOnExecutor%28java.util.concurrent.Executor,%20Params...%29 因为示例通常更具表现力,请看下面的示例。
假设我们有一个静态函数来执行一些繁重的任务,还有一个TextView,我们想要显示任务的进度和最终状态,如下所示:
static Object doHeavyTask(String string) throws Exception;

TextView progressInfo;

使用异步任务在后台线程执行任务的代码如下:
new AsyncTask<String, Integer, Exception>() {

    @Override
    protected Exception doInBackground(String... params) {
        for (int i = 0; i < params.length; i++) {
            try {
                doHeavyTask(params[i]);
            } catch (Exception e) {
                return e;
            }
            publishProgress(i, params.length);
        }
        return null;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        progressInfo.setText("Executed " + values[0] + 
            " of " + values[1] + " tasks.");
    }

    @Override
    protected void onPostExecute(Exception result) {
        if (result == null) {
            progressInfo.setText("Heavy background job done successfully!");
        }
        else {
            progressInfo.setText("Heavy background job failed!" + 
                "Exception message: " + result.getMessage());
        }
    }
}.execute("input1", "input2", "input3");

使用Thread也可以完全实现相同的功能:

final Handler handler = new Handler(Looper.getMainLooper());
final String[] params = { "input1", "input2", "input3" };
new Thread() {

    @Override
    public void run() {
        for (int i = 0; i < params.length; i++) {
            try {
                doHeavyTask(params[i]);
            } catch (final Exception e) {
                handler.post(new Runnable() {

                    @Override
                    public void run() {
                        progressInfo.setText("Heavy background job failed!" +
                            "Exception message: " + e.getMessage());
                    }
                });
                return;
            }

            final int currentIndex = i;
            handler.post(new Runnable() {

                @Override
                public void run() {
                    progressInfo.setText("Executed " + currentIndex +
                            " of " + params.length + " tasks.");
                }
            });
        }

        handler.post(new Runnable() {

            @Override
            public void run() {
                progressInfo.setText(
                    "Heavy background job done successfully!");
            }
        });
    }
}.start();

正如您在上面看到的,使用AsyncTask只是更方便一些。但除了这种便利之外,没有其他优点 :). 如果您准备好自己的任务封装线程(以及处理程序以跳回到UI线程),那么您的类可能更有效/舒适地使用。 就这些 :).

-5

您可以同时运行多个线程。但是asynctask是排队的,这意味着它一次只能运行一个任务。


3
默认情况下,AsyncTask 在单个线程上串行运行,但也可以在多个线程上并行运行。 - ElDuderino
@ElDuderino,在多线程中运行异步任务的目的/场景是什么? - twb
我不明白这个问题... AsyncTasks 总是在一个线程中运行,默认情况下是在一个线程中排队执行,而且不是并行的,但你也可以在多个线程上运行它,这样多个 AsyncTasks 就会在多个线程上执行,实现真正的并行。 - ElDuderino
你的意思是创建线程并在每个线程中运行异步任务吗? - twb
AsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - ElDuderino

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接