【问题标题】:Different between handler and AsyncTasks [duplicate]处理程序和 AsyncTasks 之间的区别 [重复]
【发布时间】:2015-01-20 06:24:37
【问题描述】:

我需要在android中使用后台操作,所以我需要知道android中handler和AsyncTasks有什么区别?

【问题讨论】:

标签: android


【解决方案1】:

Handler 和 AsyncTasks 是在 android 中使用 UI/Event Thread 实现多线程的方法。 Handler 从 Android API 级别 1 开始可用,AsyncTask 从 API 级别 3 开始可用。

什么是处理程序?

  1. 处理程序允许将消息添加到创建它的线程和它 还使您能够安排一些可运行的在某个时间执行 将来。
  2. 处理程序与应用程序的主线程相关联。它 处理和调度从后台发送的消息和可运行文件 应用主线程的线程。
  3. 如果您正在执行多个重复的任务,例如下载 要在 ImageViews 中显示的多个图像(例如 下载缩略图)下载后,使用任务队列 处理程序。
  4. 处理程序有两个主要用途。首先是调度消息 以及在未来某个时间点执行的可运行文件;第二个 是将要在不同线程上执行的操作排入队列 你自己。调度消息是通过这些方法完成的 像 post(Runnable), postAtTime(Runnable, long), postDelayed(Runnable, long), sendEmptyMessage(int), sendMessage(Message)、sendMessageAtTime(Message, long) 和 sendMessageDelayed(Message, long) 方法。
  5. 为您的应用程序创建进程时,其主线程是 专用于运行一个消息队列,负责管理 顶级应用程序对象(活动、广播接收器等) 以及他们创建的任何窗口。
  6. 您可以创建自己的线程,并与主线程进行通信 应用程序线程通过 Handler。

什么是异步任务?

  1. 异步任务使您无需获取即可实现多线程 手脏成线。 AsyncTask 使正确和易于使用 允许执行后台操作并传递 结果返回给 UI 线程。

  2. 如果你正在做一些与 UI 相关的孤立的事情,例如 下载数据以显示在列表中,继续使用 AsyncTask。 理想情况下,AsyncTasks 应该用于短操作(一些 最多几秒钟。)

  3. 异步任务由 3 种泛型类型定义,称为 Params, Progress 和 Result,以及 4 个步骤,称为 onPreExecute, doInBackground、onProgressUpdate 和 onPostExecute。

  4. 在onPreExecute中可以定义需要执行的代码 在后台处理开始之前。

  5. doInBackground 有需要在后台执行的代码, 在 doInBackground 中,我们可以将结果多次发送到 事件线程通过 publishProgress() 方法,通知后台 处理完毕,我们可以简单的返回结果。

  6. onProgressUpdate() 方法从 doInBackground 方法,通过 publishProgress 发布 方法,并且这个方法可以使用这个进度更新来更新 事件线程 onPostExecute() 方法处理返回的结果 做背景

  7. 使用的泛型类型是Params,发送的参数的类型 到执行时的任务,进度,进度的类型 在后台计算期间发布的单位。

Result,后台计算结果的类型。

  1. 如果异步任务不使用任何类型,则可以将其标记为 Void 输入。
  2. 可以通过调用 cancel(boolean) 取消正在运行的异步任务 方法。

【讨论】:

    【解决方案2】:

    简单明了的答案如下

    异步任务:

    它在不了解java线程模型的情况下给出了一个简单的线程实现,AsyncTask给出了对应于工作线程和主线程的各种回调。

    用途:用于小型等待操作,如

    从 Web 服务中获取一些数据并显示在布局上。 数据库查询。 当您意识到运行操作永远不会嵌套时。

    处理程序

    它也实现了java线程模型,它允许嵌套你运行的操作,比如从互联网上获取多个图像。

    最适合:

    1 它允许消息队列。 2.消息调度。 3. 多次长时间运行。

    线程

    现在是线程的时候了。

    线程是两者的父级,AsyncTask 在内部使用线程,这意味着您也可以创建自己的线程模型,如 AsyncTask 和 Handler 实例与单个线程和该线程的消息队列相关联。它需要对 java 多线程实现有很好的了解。

    用途:

    你可以做所有 AsyncTask 和 Handler 可以做的事情。

    【讨论】:

      【解决方案3】:

      文档说

      处理程序

      • android.os.Handler

      处理程序允许您发送和处理与线程的 MessageQueue 关联的 Message 和 Runnable 对象

      每个 Handler 实例都与单个线程和该线程的消息队列相关联。

      当您创建一个新的处理程序时,它会绑定到创建它的线程的线程/消息队列——从那时起,它会将消息和可运行对象传递到该消息队列并在它们出来时执行它们的消息队列。

      处理程序有两个主要用途:(1) 调度消息和在未来某个时间点执行的可运行文件; (2) 将要在与您自己的线程不同的线程上执行的操作排入队列

      调度消息是通过post, postAtTime(Runnable, long), postDelayed, sendEmptyMessage, sendMessage, sendMessageAtTime, and sendMessageDelayed 方法完成的。

      post 版本允许您将 Runnable 对象排入队列,以便在收到消息队列时调用它们; sendMessage 版本允许您将包含一组数据的 Message 对象排入队列,这些数据将由 Handler 的 handleMessage 方法处理(要求您实现 Handler 的子类)。

      当发布或发送到处理程序时,您可以允许在消息队列准备好后立即处理项目,或者指定处理之前的延迟或处理它的绝对时间。

      后两者允许您实现超时、滴答声和其他基于时间的行为。

      当为您的应用程序创建进程时,其主线程专用于运行消息队列,该消息队列负责管理顶级应用程序对象(活动、广播接收器等)以及它们创建的任何窗口。

      您可以创建自己的线程,并通过处理程序与主应用程序线程返回

      这是通过调用与以前相同的 post 或 sendMessage 方法来完成的,但来自您的新线程。

      给定的 Runnable 或 Message 将被调度在 Handler 的消息队列中,并在适当的时候进行处理。


      异步任务

      • android.os.AsyncTask

      AsyncTask 允许正确且轻松地使用 UI 线程。

      此类允许在 UI 线程上执行后台操作和发布结果,而无需操作线程和/或处理程序

      AsyncTask 被设计为围绕 Thread 和 Handler 的辅助类,并不构成通用线程框架

      AsyncTasks 最好用于短时间的操作(最多几秒钟。)

      如果您需要保持线程长时间运行,强烈建议您使用 java.util.concurrent 包提供的各种 API,例如 Executor、ThreadPoolExecutor 和 FutureTask。

      异步任务由在后台运行的计算线程定义,其结果发布在 UI线程上。

      异步任务由 3 个通用类型定义,称为 Params、Progress 和 Result,以及 4 个步骤,称为 onPreExecute、doInBackground、onProgressUpdate 和 onPostExecute。

      用法

      AsyncTask 必须子类化才能使用。

      子类将覆盖至少一个方法 (doInBackground),并且通常会覆盖第二个方法 (onPostExecute。)

      这是一个子类化的例子:

       private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
           protected Long doInBackground(URL... urls) {
               int count = urls.length;
               long totalSize = 0;
               for (int i = 0; i < count; i++) {
                   totalSize += Downloader.downloadFile(urls[i]);
                   publishProgress((int) ((i / (float) count) * 100));
                   // Escape early if cancel() is called
                   if (isCancelled()) break;
               }
               return totalSize;
           }
      
           protected void onProgressUpdate(Integer... progress) {
               setProgressPercent(progress[0]);
           }
      
           protected void onPostExecute(Long result) {
               showDialog("Downloaded " + result + " bytes");
           }
       }
      

      一旦创建,任务就会非常简单地执行:

      新的 DownloadFilesTask().execute(url1, url2, url3);

      AsyncTask 的泛型类型

      异步任务使用的三种类型如下:

      Params,执行时发送给任务的参数类型。 Progress,后台计算时发布的进度单元类型。 Result,后台计算结果的类型。 并非所有类型都始终由异步任务使用。要将类型标记为未使用,只需使用类型 Void:

      私有类 MyTask 扩展 AsyncTask { ... }

      四个步骤

      当一个异步任务被执行时,任务会经过4个步骤:

      onPreExecute(),在任务执行后立即在 UI 线程上调用。此步骤通常用于设置任务,例如通过在用户界面中显示进度条。

      doInBackground,在onPreExecute() 完成执行后立即在后台线程上调用。

      此步骤用于执行可能需要很长时间的后台计算。

      异步任务的参数传递到这一步。

      计算的结果必须由这一步返回,并将传回最后一步。

      此步骤还可以使用 publishProgress 来发布一个或多个进度单位。这些值在 UI 线程的 onProgressUpdate 步骤中发布。

      onProgressUpdate,在调用 publishProgress 后在 UI 线程上调用。执行的时间是不确定的。

      此方法用于在后台计算仍在执行时在用户界面中显示任何形式的进度。

      例如,它可以用于动画进度条或在文本字段中显示日志。

      onPostExecute,在后台计算完成后在 UI 线程上调用。后台计算的结果作为参数传递给该步骤。

      取消任务

      可以通过调用 cancel(boolean) 随时取消任务。调用此方法将导致对isCancelled() 的后续调用返回true。

      调用此方法后,onCancelled(Object),而不是onPostExecute(Object),将在doInBackground(Object[]) 返回后调用。

      为确保尽快取消任务,您应始终定期从doInBackground(Object[]) 检查isCancelled() 的返回值,如果可能的话(例如在循环内)。

      线程规则 要使此类正常工作,必须遵循一些线程规则:

      必须在 UI 线程上加载 AsyncTask 类。这是从android.os.Build.VERSION_CODES.JELLY_BEAN 开始自动完成的。

      任务实例必须在 UI 线程上创建。

      执行必须在 UI 线程上调用。

      请勿致电onPreExecute(), onPostExecute, doInBackground, onProgressUpdate手动

      任务只能执行一次(如果尝试第二次执行将抛出异常。)

      内存可观察性

      AsyncTask 保证所有回调调用都以这样一种方式同步,即以下操作在没有显式同步的情况下是安全的。

      在构造函数或onPreExecute中设置成员字段,并在doInBackground中引用。

      doInBackground中设置成员字段,在onProgressUpdateonPostExecute中引用。

      执行顺序

      首次引入时,AsyncTask 是在单个后台线程上串行执行的。从android.os.Build.VERSION_CODES.DONUT 开始,这已更改为允许多个任务并行运行的线程池。

      android.os.Build.VERSION_CODES.HONEYCOMB开始,任务在单线程上执行,避免并行执行导致的常见应用错误。

      如果你真的想要并行执行,你可以用THREAD_POOL_EXECUTOR.调用executeOnExecutor(java.util.concurrent.Executor, Object[])

      【讨论】:

      • 您为什么不直接发布链接而不是复制文档?大声笑,你甚至复制并粘贴了Developer Guides, For more information...
      • @Biu 感谢您的评论。它不仅仅是复制和粘贴。我做了一些编辑。你注意到了吗? .我只是想从授权来源给出答案。
      猜你喜欢
      • 2018-05-10
      • 2015-12-15
      • 2017-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多