使用AsyncTask的光明和黑暗面之四

AsyncTask替代品

由于其简单性,AsyncTask是一种流行的异步技术。 它允许在后台执行的线程可以与前台UI线程进行通信,提供通用且适应性强的异步技术,AsyncTask本身没有施加任何约束。 但是,正如我们看到的那样,您需要考虑几个问题:

  • 由于AsyncTask具有全局执行环境,因此您使用AsyncTask执行的任务越多,由于应用程序中还有其他执行环境的任务,将无法按预期处理任务的风险就越高。
  • 不同平台版本的执行环境中的不一致性使得优化执行的性能(并发执行)或线程安全(顺序执行)变得更加困难。

由于AsyncTask的简单性,它经常在应用程序中过度使用。 但它不是在Android上异步执行的灵丹妙药。 对于许多场景而言,出于体系结构,程序设计的原因,或者仅仅是因为它们不太容易出错,您应该研究替代技术。

 

轻松实现AsyncTask时

AsyncTask可能导致比其他方法更复杂的两个简单用例是:

  1. 在没有参数的情况下执行任务(AsyncTask

没有定义任何参数的AsyncTask不能在UI线程和后台线程之间传递数据。 无法将数据输入到后台线程中,无法报告进度,也没有结果从后台线程传递到UI线程。

    2. 只实现doInBackground方法

没有提供进度更新或报告结果的回调,AsyncTask仅仅是一个后台线程。

对于这两种情况,我们最好用Thread或者HandlerThread来替代。


需要循环调用的后台任务

在AsyncTask下执行后台任务的工作线程没有关联的Looper或MessageQueue,因此消息传递是不可行的。 从理论上讲,可以将Looper与doInBackground或已执行的Runnable中的工作线程相关联,但这将阻塞正在使用的工作线程,直到Looper完成。 当顺序执行生效时,它将阻止应用程序中的所有其他AsyncTask执行。
即使Looper刚刚准备就绪,但没有遍历消息队列,也不会从工作线程中删除它,以便其他任务执行可以使用该线程。 如果第二个任务试图在该线程上准备另一个Looper,则将引发RuntimeException。
如果您的应用程序需要Looper,请使用HandlerThread而不是AsyncTask。

本地服务(Local Service)

Local Service与应用程序中的其他组件并行执行,通常用于处理长操作的执行。Service在应用程序的UI线程中执行,需要额外的后台线程来执行长时间的操作。AsyncTask是一个候选对象,但是全局执行任务的应用程序允许其他组件同时利用执行环境,并相互干扰。

因此,Service应当使用这些备选解决方案之一:

  • Thread 
  • The Executor framework 
  • HandlerThread 
  • An AsyncTask with a custom executor
     

 

使用execute(Runnable)方法运行AsyncTask

execute(Runable)方法会消除AsyncTask的主要优点;它只是将Runnable放在工作队列中,并在线程池中有空闲线程可用时运行它。因为没有启用消息传递,所以UI线程将不会收到任何回调。因此,这个用例就像普通线程的执行,但是有两个主要区别:

  •  优点:该任务在可能已经存在的AsyncTask内部线程池中执行,这使其资源效率更高。
  •  缺点:任务始终在应用程序全局执行环境中执行,并且可能会干扰其他任务。

最好使用Thread或者Executor框架替代

你可能感兴趣的:(使用AsyncTask的光明和黑暗面之四)