AsyncTask源码分析 & 深层次BUG

(1)AsyncTask 4大回调方法的执行线程

doInBackground

publicProgress

preExecute

postExectue


通常我们的理解是:

doInBackground :异步线程

publicProgress :主线程

preExecute:主线程

postExectue:主线程


但实际上,如果你真这么想,你可得当心了,因为由于安卓系统的Bug,这些方法的执行线程未必如你想的那样。


1. preExecute 和你调用AsyncTask.execute()在同一个线程

这也意味着,如果你在非UI线程里面调用execute()话,在preExecute中执行UI更新操作,很可能会导致异常


2. postExectue, publicProgress使用的是sHandler初始化绑定的线程

通常情况下的安卓系统都会在主线程中加载AsyncTask类,这样sHandler默认会绑定到主线程上,

那么postExectue和publicProgress默认将在主线程中执行,这并没有什么问题。


但是,假设系统有bug,它不在主线程中初始化AsyncTask,那么postExectue中执行某些UI操作将会导致异常。

(你可以自己实现一个AsyncTask,然后在非UI线程中加载它,然后看看各个方法的执行对应线程)


3 doInBackground 的执行线程

这个线程是线程池为你分配的一个线程,也就是说它默认情况下是没有进行办法初始化Handler的。


这就意味着,在极端情况下,这4个回调方法可能在3个不同的线程中执行,并且还都不是主线程。


(2) AsyncTask 线程阻塞

在doInBackground 执行网络拉取操作是错误的写法!!


因为在安卓3.0 之后,AsyncTask的默认执行器是顺序执行的。

它会一个一个的执行你的任务,而不是并发的执行这些任务。

除了第一次,之后scheduleNext();  一定在r.run();后执行,
所以即使是并发线程池,也就一个Runnable执行而已。
所以,网络拉取操作可能阻塞其他AsyncTask.不建议在doBackground中执行。

如果你一定要这么干,请为AsyncTask分配一个额外的执行器。

或者使用v4包里面的AsyncTask.

你可能感兴趣的:(Java,Android)