【问题标题】:When to use AsyncTask and When to use Thread in Android在 Android 中何时使用 AsyncTask 和何时使用 Thread
【发布时间】:2014-04-08 09:26:01
【问题描述】:

何时使用AsyncTask 和何时使用Thread,因为两者都在后台工作,并且都可以通过某种机制操作UI Thread 中的控件..

【问题讨论】:

  • 当您在运行并行任务时没有问题时,对于同一件事,即假设您要处理不同的计算,您只需从一个线程开始。对于 asyncTask,当您需要从后台工作返回某些内容,或者想要等待某个进程完成后再执行某个其他进程或更新某个视图等时。
  • 我的要求是点击服务,然后检索一些数据并将对象列表保留在列表中,并更新 ui 以获取其进度,检索可能需要时间

标签: android multithreading android-asynctask


【解决方案1】:

希望对您有所帮助:

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

AsyncTask 主要用于:

  • 无需下载大量数据的简单网络操作
  • 可能需要超过几毫秒的磁盘绑定任务

并将 Java 线程用于:

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

有关详细信息,请参阅 莫希特的回答Click Here

编辑:

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

线程是线程,可能你已经从其他部分知道了。您需要知道您不能从线程更新 UI。您需要为此使用处理程序,并且有时停止线程也会出现问题。线程是一种在不阻塞其他工作的情况下完成工作的机制......

服务不代表线程,线程也不代表服务。两者都不一样..

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

【讨论】:

  • 我会完全通过 Thread 类并选择“新”执行器框架 + Runnable/Callable+Future。
【解决方案2】:

AsyncTask 只是 Android SDK 提供的一个“帮助”类,以便在后台任务完成后更容易跳到 UI 线程。它建立在标准的 Java 线程 API 之上。它不会提供仅用线程无法完成的事情。它解决了在短任务运行后台线程和UI线程之间切换的常见场景。

一般来说,当后台任务完成后必须“跳回”到 UI 线程或在任务执行期间必须向 UI 线程提供一些反馈时,使用 AsyncTask 会很方便。否则只是开销。

您不必强制使用 AsyncTask。如果您作为开发人员更喜欢直接使用Threads 或Futures,您可以使用它并在后台任务完成后手动跳到 UI 线程。

编辑:

此处的其他一些答案表明,使用 AsyncTask 应仅限于短任务。据称是因为它使用了一个公共池。然而,自从 API 级别 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 更方便一些。但是没有其他优势,就是这种方便:)。 如果您准备了自己的任务来封装 Thread(以及一个 Handler 以跳回 UI 线程),那么您的类可能会更高效/更方便您使用。 就是这样:)。

【讨论】:

    【解决方案3】:

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

    【讨论】:

    • 默认情况下,AsyncTask 在单线程中串行运行,但您也可以在多个线程中并行运行。
    • @ElDuderino 以及在多线程中运行 asyntask 的目的/场景?
    • 我不明白这个问题... AsyncTasks 总是在一个线程中运行,默认情况下在一个线程中(排队,串行,不是并行),但你也可以在多个线程上运行它,因此多个 AsyncTask 在多个线程上执行 == 真正的并行性。
    • 你的意思是创建线程并在每个线程中运行一个异步任务吗?
    • AsyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    猜你喜欢
    • 2012-08-12
    • 1970-01-01
    • 2013-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多