Looper 和Handler 是理解好AsyncTask的一个基础,我们可以先从这里开始,先给出一个主线程和子线程互相通信的例子。

 package com.example.loopertest;

 import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log; public class MainActivity extends Activity { public static final int SIGNAL_1 = 0x1;
public static final int SIGNAL_2 = 0x2; public static int flagValue = 0;
private LooperThread thread;
private Handler uiHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
switch (msg.what) {
case SIGNAL_1:
Log.v("MainActivity", "主线程收到子线程发来的消息");
flagValue++;
if (flagValue == 5) {
Log.v("MainActivity", "now flagvalue is over 5");
Log.v("MainActivity",
"quit 前 thread.isAlive?" + thread.isAlive());
thread.cHandler.getLooper().quit();
Log.v("MainActivity",
"quit 后 thread.isAlive?" + thread.isAlive());
} else {
Log.v("MainActivity", "thread.isAlive?" + thread.isAlive());
thread.cHandler.sendEmptyMessageDelayed(SIGNAL_1, 3000);
}
break;
case SIGNAL_2:
thread.cHandler.sendEmptyMessage(SIGNAL_1);
break;
default:
break;
}
}
}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); thread = new LooperThread();
thread.start();
uiHandler.sendEmptyMessage(SIGNAL_2); new Thread() {
public void run() {
while (true) {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Log.v("MainActivity",
"第三个子线程里面每隔10s判断 thread.isAlive?"
+ thread.isAlive());
}
}
}.start(); } class LooperThread extends Thread {
public Handler cHandler; @Override
public void run() { // 实例化messagequeue
Looper.prepare(); cHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
switch (msg.what) {
case SIGNAL_1:
Log.v("MainActivity", "子线程收到主线程发来的消息");
uiHandler.sendEmptyMessageDelayed(SIGNAL_1, 3000);
break;
default:
break;
}
}
};
Log.v("MainActivity", "loop以前的语句");
Looper.loop(); Log.v("MainActivity", "loop以后的语句"); } } }

看一下执行结果

04-30 07:17:58.754: V/MainActivity(597): loop以前的语句
04-30 07:17:58.784: V/MainActivity(597): 子线程收到主线程发来的消息
04-30 07:18:01.794: V/MainActivity(597): 主线程收到子线程发来的消息
04-30 07:18:01.794: V/MainActivity(597): thread.isAlive?true
04-30 07:18:04.804: V/MainActivity(597): 子线程收到主线程发来的消息
04-30 07:18:07.814: V/MainActivity(597): 主线程收到子线程发来的消息
04-30 07:18:07.814: V/MainActivity(597): thread.isAlive?true
04-30 07:18:08.780: V/MainActivity(597): 第三个子线程里面每隔10s判断 thread.isAlive?true
04-30 07:18:10.824: V/MainActivity(597): 子线程收到主线程发来的消息
04-30 07:18:13.834: V/MainActivity(597): 主线程收到子线程发来的消息
04-30 07:18:13.834: V/MainActivity(597): thread.isAlive?true
04-30 07:18:16.844: V/MainActivity(597): 子线程收到主线程发来的消息
04-30 07:18:18.782: V/MainActivity(597): 第三个子线程里面每隔10s判断 thread.isAlive?true
04-30 07:18:19.844: V/MainActivity(597): 主线程收到子线程发来的消息
04-30 07:18:19.844: V/MainActivity(597): thread.isAlive?true
04-30 07:18:22.854: V/MainActivity(597): 子线程收到主线程发来的消息
04-30 07:18:25.864: V/MainActivity(597): 主线程收到子线程发来的消息
04-30 07:18:25.864: V/MainActivity(597): now flagvalue is over 5
04-30 07:18:25.864: V/MainActivity(597): quit 前 thread.isAlive?true
04-30 07:18:25.874: V/MainActivity(597): loop以后的语句
04-30 07:18:25.874: V/MainActivity(597): quit 后 thread.isAlive?false
04-30 07:18:28.785: V/MainActivity(597): 第三个子线程里面每隔10s判断 thread.isAlive?false

这个例子就是用来 在android里面 主线程和子线程进行通信的,大家可以看一下代码,另外还有第三个线程在不断侦测 子线程如何结束。

实际上就是子线程和主线程每隔3s 通信一次,然后通信的时候那个参数值  就每次加1,一直加到5的时候 子线程就结束了。

例子里面也可以看出来 looper的消息队列在没有quit的时候 子线程是会一直执行的,也就是谁looper.loop()后面的代码是不会执行的,

只有当quit以后 loop()的代码才会执行,这点大家要注意了。

然后我们可以借着这个清晰得例子,来理一下 looper和handler之间是如何通信的。

首先我们调用的是Looper.prepare(); 这句话,我们来看一下源码是怎么写的,

  public static void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}

一下就能看出来 如果get()的值不是空 那么就要抛出这个异常,这样就能解释我们一个线程 肯定只能有一个looper了,并且Looper.prepare() 在一个线程里面只能调用一次,否则也要抛异常。

当然了 我们可以点到这个set方法里面看一下 大概做了什么操作。

  // sThreadLocal.get() will return null unless you've called prepare().
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

然后我们进入threadlocal这个类里面的set方法看看。

 /**
* Sets the value of this variable for the current thread. If set to
* {@code null}, the value will be set to null and the underlying entry will
* still be present.
*
* @param value the new value of the variable for the caller thread.
*/
public void set(T value) {
Thread currentThread = Thread.currentThread();
Values values = values(currentThread);
if (values == null) {
values = initializeValues(currentThread);
}
values.put(this, value);
}

到这个地方就很明显了 看第9行,

 Thread currentThread = Thread.currentThread();

这也就是为什么说一个线程只能有一个looper。也能说明Looper和线程的绑定 就是在这个方法里面完成的。有兴趣的同学还可以继续看values这个内部类,我们在这里先不去挖的太深。

说完prepare 方法 我们再说说loop方法,因为有很多人都不明白 为什么loop方法以后的语句 都不执行。我们还是直接上源代码。

  /**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public static void loop() {
Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
MessageQueue queue = me.mQueue; // Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident = Binder.clearCallingIdentity(); while (true) {
Message msg = queue.next(); // might block
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
} long wallStart = 0;
long threadStart = 0; // This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
wallStart = SystemClock.currentTimeMicro();
threadStart = SystemClock.currentThreadTimeMicro();
} msg.target.dispatchMessage(msg); if (logging != null) {
long wallTime = SystemClock.currentTimeMicro() - wallStart;
long threadTime = SystemClock.currentThreadTimeMicro() - threadStart; logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
if (logging instanceof Profiler) {
((Profiler) logging).profile(msg, wallStart, wallTime,
threadStart, threadTime);
}
} // Make sure that during the course of dispatching the
// identity of the thread wasn't corrupted.
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x"
+ Long.toHexString(ident) + " to 0x"
+ Long.toHexString(newIdent) + " while dispatching to "
+ msg.target.getClass().getName() + " "
+ msg.callback + " what=" + msg.what);
} msg.recycle();
}
}
}

6-10行 我们能看出来 是取得了 looper的 消息队列,然后17行开始 就是一个while true循环了!这也就能解释为啥loop方法一调用我们loop后面的代码就不会执行,

18行也能看出来,代码告诉我们是不断的在消息队列里面取消息,并且有可能会阻塞~

我们再来看一下这个37行的代码

msg.target.dispatchMessage(msg);

到这个地方 可能很多人就能猜到了,这个地方就是我们处理消息的地方。那么这个msg.target我们应该怎么理解?(很多人无法理解looper handler 之间的关系 其实是因为这个地方始终理解不了)

我们可以先放一放,先去看我们handler的代码,在我们文中开头的第一个例子中,我们在prepare()以后 就创建了一个handler,

我们去看看handler的构造函数。

  /**
* Default constructor associates this handler with the queue for the
* current thread.
*
* If there isn't one, this handler won't be able to receive messages.
*/
public Handler() {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
} mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = null;
}

17-21行 可以看出来,我们在调用handler的构造函数的时候,会先取当前线程的looper 如果取不到就会报异常了~~

然后我们发消息的时候是调用的send函数,

 /**
* Sends a Message containing only the what value, to be delivered
* after the specified amount of time elapses.
* @see #sendMessageDelayed(android.os.Message, long)
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}

经过一番调查,我们发现最终都是调用的这个方法

 /**
* Enqueue a message into the message queue after all pending messages
* before the absolute time (in milliseconds) <var>uptimeMillis</var>.
* <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
* You will receive it in {@link #handleMessage}, in the thread attached
* to this handler.
*
* @param uptimeMillis The absolute time at which the message should be
* delivered, using the
* {@link android.os.SystemClock#uptimeMillis} time-base.
*
* @return Returns true if the message was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting. Note that a
* result of true does not mean the message will be processed -- if
* the looper is quit before the delivery time of the message
* occurs then the message will be dropped.
*/
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
{
boolean sent = false;
MessageQueue queue = mQueue;
if (queue != null) {
msg.target = this;
sent = queue.enqueueMessage(msg, uptimeMillis);
}
else {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
}
return sent;
}

注意看 24行,

msg.target = this;

然后我们回到loop方法里面

msg.target.dispatchMessage(msg);

一下就能看出来,其实target就是handler。

所以loop方法里面处理消息实际上就是调用的handler的dispatchMessage 这个方法!

我们进去看这个方法

 /**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}

看14行,发现其实调用的是handler的这个方法

  /**
* Subclasses must implement this to receive messages.
*/
public void handleMessage(Message msg) {
}

而这个方法 也是我们每次都去重写的。到这里 我们就算是理清楚了 handler 和looper 之间消息传递的一个过程。

其实就是 先调用looper.prepare() 然后才能创建handler. 一个线程只能有一个looper 一个线程队列 messagequeue.

handler发消息的时候 发message的时候 实际上是把自己(handler本身)放在了message的 target变量里面,这样在loop

方法里面无线循环的时候 我们才能回调到 handler的handleMessage方法~~~~

同样的我们也可以分析一下 为什么quit方法 可以让loop循环结束?(我就不分析了 留给大家自己分析 其实也是不难的)

搞清楚looper和handler的关系以后 我们就可以看看 AsyncTask这个东西。

 package com.example.asynctest;

 import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.widget.TextView; public class MainActivity extends Activity { private TextView tv1; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv1 = (TextView) this.findViewById(R.id.tv1);
/**
* Task的实例必须在UI thread中创建; execute方法必须在UI thread中调用;
* 不要手动的调用onPreExecute(),
* onPostExecute(Result),doInBackground(Params...),
* onProgressUpdate(Progress...)这几个方法; 该task只能被执行一次,否则多次调用时将会出现异常;
*/
new MyAsyncTask().execute(); } private class MyAsyncTask extends AsyncTask<Void, Integer, Void> { @Override
protected void onPreExecute() {
// TODO Auto-generated method stub
Log.v("mainactivity", Thread.currentThread().getName()
+ " onPreExecute ");
} /**
* 这里不能直接操作ui 因为不是在主线程里操作的
*/
@Override
protected Void doInBackground(Void... params) {
// TODO Auto-generated method stub
// 模拟数据的加载,耗时的任务
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(80);
} catch (InterruptedException e) {
e.printStackTrace();
}
publishProgress(i);
} Log.v("mainactivity", Thread.currentThread().getName()
+ " doInBackground ");
return null;
} /**
* 在主线程执行
*/
@Override
protected void onProgressUpdate(Integer... values) {
tv1.setText(values[0] + "");
Log.v("mainactivity", Thread.currentThread().getName()
+ " onProgressUpdate ");
} /**
* 可以操作ui
*/
@Override
protected void onPostExecute(Void result) {
// 进行数据加载完成后的UI操作
tv1.setText("LOAD DATA SUCCESS ");
Log.e("mainactivity", Thread.currentThread().getName()
+ " onPostExecute ");
}
} }

我们看一下 日志和运行效果。

看一下日志

04-30 09:04:16.345: V/mainactivity(935): main onPreExecute
04-30 09:04:16.494: V/mainactivity(935): main onProgressUpdate
04-30 09:04:16.884: V/mainactivity(935): main onProgressUpdate
04-30 09:04:16.914: V/mainactivity(935): main onProgressUpdate
04-30 09:04:16.914: V/mainactivity(935): main onProgressUpdate
04-30 09:04:16.914: V/mainactivity(935): main onProgressUpdate
04-30 09:04:17.264: V/mainactivity(935): main onProgressUpdate
04-30 09:04:17.264: V/mainactivity(935): main onProgressUpdate
04-30 09:04:17.284: V/mainactivity(935): main onProgressUpdate
04-30 09:04:17.284: V/mainactivity(935): main onProgressUpdate
04-30 09:04:17.365: V/mainactivity(935): main onProgressUpdate
04-30 09:04:17.414: V/mainactivity(935): main onProgressUpdate
04-30 09:04:17.414: V/mainactivity(935): main onProgressUpdate
04-30 09:04:17.484: V/mainactivity(935): main onProgressUpdate
04-30 09:04:17.534: V/mainactivity(935): main onProgressUpdate
04-30 09:04:17.614: V/mainactivity(935): main onProgressUpdate
04-30 09:04:17.684: V/mainactivity(935): main onProgressUpdate
04-30 09:04:17.754: V/mainactivity(935): main onProgressUpdate
04-30 09:04:17.834: V/mainactivity(935): main onProgressUpdate
04-30 09:04:17.914: V/mainactivity(935): main onProgressUpdate
04-30 09:04:17.994: V/mainactivity(935): main onProgressUpdate
04-30 09:04:18.074: V/mainactivity(935): main onProgressUpdate
04-30 09:04:18.154: V/mainactivity(935): main onProgressUpdate
04-30 09:04:18.244: V/mainactivity(935): main onProgressUpdate
04-30 09:04:18.324: V/mainactivity(935): main onProgressUpdate
04-30 09:04:18.404: V/mainactivity(935): main onProgressUpdate
04-30 09:04:18.484: V/mainactivity(935): main onProgressUpdate
04-30 09:04:18.565: V/mainactivity(935): main onProgressUpdate
04-30 09:04:18.644: V/mainactivity(935): main onProgressUpdate
04-30 09:04:18.724: V/mainactivity(935): main onProgressUpdate
04-30 09:04:18.804: V/mainactivity(935): main onProgressUpdate
04-30 09:04:18.884: V/mainactivity(935): main onProgressUpdate
04-30 09:04:18.964: V/mainactivity(935): main onProgressUpdate
04-30 09:04:19.053: V/mainactivity(935): main onProgressUpdate
04-30 09:04:19.134: V/mainactivity(935): main onProgressUpdate
04-30 09:04:19.214: V/mainactivity(935): main onProgressUpdate
04-30 09:04:19.294: V/mainactivity(935): main onProgressUpdate
04-30 09:04:19.375: V/mainactivity(935): main onProgressUpdate
04-30 09:04:19.454: V/mainactivity(935): main onProgressUpdate
04-30 09:04:19.534: V/mainactivity(935): main onProgressUpdate
04-30 09:04:19.614: V/mainactivity(935): main onProgressUpdate
04-30 09:04:19.694: V/mainactivity(935): main onProgressUpdate
04-30 09:04:19.784: V/mainactivity(935): main onProgressUpdate
04-30 09:04:19.864: V/mainactivity(935): main onProgressUpdate
04-30 09:04:19.944: V/mainactivity(935): main onProgressUpdate
04-30 09:04:20.024: V/mainactivity(935): main onProgressUpdate
04-30 09:04:20.104: V/mainactivity(935): main onProgressUpdate
04-30 09:04:20.184: V/mainactivity(935): main onProgressUpdate
04-30 09:04:20.264: V/mainactivity(935): main onProgressUpdate
04-30 09:04:20.344: V/mainactivity(935): main onProgressUpdate
04-30 09:04:20.425: V/mainactivity(935): main onProgressUpdate
04-30 09:04:20.504: V/mainactivity(935): main onProgressUpdate
04-30 09:04:20.593: V/mainactivity(935): main onProgressUpdate
04-30 09:04:20.674: V/mainactivity(935): main onProgressUpdate
04-30 09:04:20.754: V/mainactivity(935): main onProgressUpdate
04-30 09:04:20.834: V/mainactivity(935): main onProgressUpdate
04-30 09:04:20.914: V/mainactivity(935): main onProgressUpdate
04-30 09:04:20.994: V/mainactivity(935): main onProgressUpdate
04-30 09:04:21.073: V/mainactivity(935): main onProgressUpdate
04-30 09:04:21.154: V/mainactivity(935): main onProgressUpdate
04-30 09:04:21.233: V/mainactivity(935): main onProgressUpdate
04-30 09:04:21.313: V/mainactivity(935): main onProgressUpdate
04-30 09:04:21.404: V/mainactivity(935): main onProgressUpdate
04-30 09:04:21.485: V/mainactivity(935): main onProgressUpdate
04-30 09:04:21.563: V/mainactivity(935): main onProgressUpdate
04-30 09:04:21.643: V/mainactivity(935): main onProgressUpdate
04-30 09:04:21.723: V/mainactivity(935): main onProgressUpdate
04-30 09:04:21.803: V/mainactivity(935): main onProgressUpdate
04-30 09:04:21.883: V/mainactivity(935): main onProgressUpdate
04-30 09:04:21.963: V/mainactivity(935): main onProgressUpdate
04-30 09:04:22.043: V/mainactivity(935): main onProgressUpdate
04-30 09:04:22.123: V/mainactivity(935): main onProgressUpdate
04-30 09:04:22.204: V/mainactivity(935): main onProgressUpdate
04-30 09:04:22.293: V/mainactivity(935): main onProgressUpdate
04-30 09:04:22.373: V/mainactivity(935): main onProgressUpdate
04-30 09:04:22.454: V/mainactivity(935): main onProgressUpdate
04-30 09:04:22.533: V/mainactivity(935): main onProgressUpdate
04-30 09:04:22.613: V/mainactivity(935): main onProgressUpdate
04-30 09:04:22.693: V/mainactivity(935): main onProgressUpdate
04-30 09:04:22.773: V/mainactivity(935): main onProgressUpdate
04-30 09:04:22.854: V/mainactivity(935): main onProgressUpdate
04-30 09:04:22.934: V/mainactivity(935): main onProgressUpdate
04-30 09:04:23.024: V/mainactivity(935): main onProgressUpdate
04-30 09:04:23.103: V/mainactivity(935): main onProgressUpdate
04-30 09:04:23.184: V/mainactivity(935): main onProgressUpdate
04-30 09:04:23.264: V/mainactivity(935): main onProgressUpdate
04-30 09:04:23.344: V/mainactivity(935): main onProgressUpdate
04-30 09:04:23.424: V/mainactivity(935): main onProgressUpdate
04-30 09:04:23.504: V/mainactivity(935): main onProgressUpdate
04-30 09:04:23.584: V/mainactivity(935): main onProgressUpdate
04-30 09:04:23.664: V/mainactivity(935): main onProgressUpdate
04-30 09:04:23.744: V/mainactivity(935): main onProgressUpdate
04-30 09:04:23.834: V/mainactivity(935): main onProgressUpdate
04-30 09:04:23.914: V/mainactivity(935): main onProgressUpdate
04-30 09:04:23.994: V/mainactivity(935): main onProgressUpdate
04-30 09:04:24.074: V/mainactivity(935): main onProgressUpdate
04-30 09:04:24.154: V/mainactivity(935): main onProgressUpdate
04-30 09:04:24.234: V/mainactivity(935): main onProgressUpdate
04-30 09:04:24.314: V/mainactivity(935): main onProgressUpdate
04-30 09:04:24.394: V/mainactivity(935): main onProgressUpdate
04-30 09:04:24.474: V/mainactivity(935): AsyncTask #5 doInBackground
04-30 09:04:24.474: V/mainactivity(935): main onProgressUpdate

 其实还是蛮好理解的,可以清楚的看到

AsyncTask

的执行周期 以及那些方法都是在哪个线程执行的(ui还是子?)

然后 我们就来分析一下 这个AsyncTask类到底是怎么做的?

这是我们调用的excute方法,
 public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}

跟进去 看看。

 public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
throw new IllegalStateException("Cannot execute task:"
+ " the task is already running.");
case FINISHED:
throw new IllegalStateException("Cannot execute task:"
+ " the task has already been executed "
+ "(a task can be executed only once)");
}
} mStatus = Status.RUNNING; onPreExecute(); mWorker.mParams = params;
exec.execute(mFuture); return this;
}

3-13行 我们可以看出来,这个excute方法 只能执行一次,不然就要抛异常。同时 也能看出来

onPreExecute(); 这个方法是在主线程执行的。

然后我们着重看一下19行,这个地方,mWorker 是什么?

找了一下 发现
     private final WorkerRunnable<Params, Result> mWorker;

实际上 是Workerrunnable这个类的对象,我们进去看看这个类。

 private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
Params[] mParams;
}

发现这是一个静态的抽象类~并且继承了

Callable 这个接口

当然了 因为这是抽象类,所以我们无需实现这个接口。

既然
mWorker  是 WorkerRunnable 他的对象,哪我们去看看 是如何new出来的呢?看构造方法
 /**
* Creates a new asynchronous task. This constructor must be invoked on the UI thread.
*/
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
return postResult(doInBackground(mParams));
}
}; mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
try {
final Result result = get(); postResultIfNotInvoked(result);
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occured while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
} catch (Throwable t) {
throw new RuntimeException("An error occured while executing "
+ "doInBackground()", t);
}
}
};
}
到这 我们相信 mWorker大家已经知道是怎么回事了  5-12行表明了mWorker 是一个对象,并且他的回调方法里面 也调用了
doInBackground 这个方法,至与
postResult 这个方法 我们可以等会再看,先往下面继续看,我们再拿到
mWorker 这个对象以后 又利用他 去初始化了
mFuture  这个对象,且这个对象是由
FutureTask 这个类生成的,哪我们就去看看这个类。
public class FutureTask<V> implements RunnableFuture<V> {

发现 这类 继承自 RunnableFuture 这个接口,哪我们去看看这个接口,

public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
void run();
}

我们发现原来 看似复杂的FutureTask 也不过就是一个Runnable 对象吗~~

回到excute方法

我们发现了 这句话

exec.execute(mFuture);

实际上 就是这么调用的

 public final AsyncTask<Params, Progress, Result> execute(Params... params) {
return executeOnExecutor(sDefaultExecutor, params);
}

那么我们赶紧去看一下 sDefaultExecutor 这是什么东西?

    private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

再看看

SERIAL_EXECUTOR 这是什么?

/**
* An {@link Executor} that executes tasks one at a time in serial
* order. This serialization is global to a particular process.
*/
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();

原来是一个静态的 final 对象~~且这个对象是由SerialExecutor 这个类生成的,哪我们赶紧去看一下这个类,

 private static class SerialExecutor implements Executor {
final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
Runnable mActive; public synchronized void execute(final Runnable r) {
mTasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (mActive == null) {
scheduleNext();
}
} protected synchronized void scheduleNext() {
if ((mActive = mTasks.poll()) != null) {
THREAD_POOL_EXECUTOR.execute(mActive);
}
}
}

第二行 明显的 是创建了一个线程队列

当执行excute方法的时候

实际上就是把这个runnable 先放到线程队列里面,然后再去执行线程队列里的第一个线程,

20-24行 就是从这个线程队列里面取值,如果能取到 就执行这句话

THREAD_POOL_EXECUTOR.execute(mActive);

而THREAD_POOL_EXECUTOR就是一个线程池。

 /**
* An {@link Executor} that can be used to execute tasks in parallel.
*/
public static final Executor THREAD_POOL_EXECUTOR
= new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

也可以看一下这个常量


  private static final int CORE_POOL_SIZE = 5;
private static final int MAXIMUM_POOL_SIZE = 128;
private static final int KEEP_ALIVE = 1;
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new LinkedBlockingQueue<Runnable>(10);

有兴趣的可以看下这个线程池的参数设置。

但实际上我们回到

SerialExecutor 

这个类的5=15行 

我们发现 实际上我们还是从队列里面取任务出来做,任务做完了,才去取下一个任务。

所以 AsyncTask 他本质上还是一个单线程执行的 东西,(当然执行的时候是在子线程 而不是主线程执行的)

我们再回到一开始的地方 
 public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
Params... params) {
if (mStatus != Status.PENDING) {
switch (mStatus) {
case RUNNING:
throw new IllegalStateException("Cannot execute task:"
+ " the task is already running.");
case FINISHED:
throw new IllegalStateException("Cannot execute task:"
+ " the task has already been executed "
+ "(a task can be executed only once)");
}
} mStatus = Status.RUNNING; onPreExecute(); mWorker.mParams = params;
exec.execute(mFuture); return this;
}

实际上我们执行的 就是mFuture 这个任务,这个任务在子线程里面被执行。

所以我们去看一下FutureTask 他的run方法

 /**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
public void run() {
sync.innerRun();
}

找到run方法

  void innerRun() {
if (!compareAndSetState(READY, RUNNING))
return; runner = Thread.currentThread();
if (getState() == RUNNING) { // recheck after setting thread
V result;
try {
result = callable.call();
} catch (Throwable ex) {
setException(ex);
return;
}
set(result);
} else {
releaseShared(0); // cancel
}
}

可以看出来 run方法实际执行的是

callable.call 这个方法,所谓这个方法 不过也是我们一开始构造函数里的mWorker对象罢了,
   public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
mTaskInvoked.set(true); Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
return postResult(doInBackground(mParams));
}
}; mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
try {
final Result result = get(); postResultIfNotInvoked(result);
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occured while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
} catch (Throwable t) {
throw new RuntimeException("An error occured while executing "
+ "doInBackground()", t);
}
}
};
}
所以线程中执行的是3-8行里的代码!!!!!!!!!!!!!!!!!!!!!!!!!!

所以doInBackground 这方法是在子线程里面去执行的。

执行完毕以后才调用了下面的方法
 private Result postResult(Result result) {
Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
new AsyncTaskResult<Result>(this, result));
message.sendToTarget();
return result;
}

最终我们找到这个handler里面看一下 看看这里面做了什么。

 private static class InternalHandler extends Handler {
@SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
@Override
public void handleMessage(Message msg) {
AsyncTaskResult result = (AsyncTaskResult) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
// There is only one result
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}

再看看这个finish方法

  private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
于是 整个AsyncTask的生命周期 就全部得到印证,执行顺序 到这里也就差不多了。

至此 我们 AsyncTask,Looper,Handler 这三者的源码分析 也就告一段落。


 

---恢复内容结束---

正确理解 AsyncTask,Looper,Handler三者之间的关系(基于android 4.0)的更多相关文章

  1. 【Linux网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系

    [Linux网络编程]TCP网络编程中connect().listen()和accept()三者之间的关系 基于 TCP 的网络编程开发分为服务器端和客户端两部分,常见的核心步骤和流程如下: conn ...

  2. silverlight Canvas、StackPanel、Grid三者之间的关系

    学习 silverlight   首先Canvas.StackPanel.Grid 博客园里看到jailu的这篇文章整理得很好 贴下来: Silverlight提供了非常灵活的布局管理系统,让程序员和 ...

  3. 转:spring data jpa、 hibernate、 jpa 三者之间的关系

    原文链接:spring data jpa. hibernate. jpa 三者之间的关系 spring data jpa hibernate jpa 三者之间的关系 JPA规范与ORM框架之间的关系是 ...

  4. Window系统、主函数和窗体函数这三者之间的关系

    理解Window系统.主窗体.窗体函数这三者之间的关系,对于编写Windows程序十分重要. 主函数和窗体函数都是由Windows系统来调用的函数.仅仅只是主函数是程序启动之后.系统首先调用的函数: ...

  5. 【面向对象】----【prototype&&__proto__&&实例化对象三者之间的关系】(四)-----【巷子】

    1.构造函数 a.什么是构造函数? 解释:通过关键字new 创建的函数叫做构造函数 作用:用来创建一个对象 废话少说直接上代码,首先我们还是创建一个构造函数人类 然后我们在创建两个实例,一个凡尘 一个 ...

  6. 【面向对象】【prototype&&__proto__&&实例化对象三者之间的关系】

    1.构造函数 a.什么是构造函数? 解释:通过关键字new 创建的函数叫做构造函数 作用:用来创建一个对象 废话少说直接上代码,首先我们还是创建一个构造函数人类 然后我们在创建两个实例,一个凡尘 一个 ...

  7. 面向对象---prototype、__proto__、实例化对象三者之间的关系

    1.构造函数 a.什么是构造函数? 解释:通过关键字new 创建的函数叫做构造函数 作用:用来创建一个对象 废话少说直接上代码,首先我们还是创建一个构造函数人类 然后我们在创建两个实例,一个凡尘 一个 ...

  8. tep环境变量、fixtures、用例三者之间的关系

    tep是一款测试工具,在pytest测试框架基础上集成了第三方包,提供项目脚手架,帮助以写Python代码方式,快速实现自动化项目落地. 在tep项目中,自动化测试用例都是放到tests目录下的,每个 ...

  9. js中数据、内存、变量的概念及三者之间的关系

    目录 数据.内存.变量的概念及三者之间的关系 什么是数据 数据的特点 什么是内存 栈内存 堆内存 JS引擎如何管理内存 什么是变量 变量是普通类型时 变量是引用类型时 数据.内存.变量的三者之间的关系 ...

随机推荐

  1. Gradle Goodness: Skip Building Project Dependencies

    If we use Gradle in a multi-module project we can define project dependencies between modules. Gradl ...

  2. Project Euler 110:Diophantine reciprocals II 丢番图倒数II

    Diophantine reciprocals II In the following equation x, y, and n are positive integers. For n = 4 th ...

  3. skip list

    概述 Skip list是平衡树的一种替代的数据结构,但是和红黑树不相同的是,跳表对于树的平衡的实现是基于一种随机化的算法的,这样也就是说跳表的插入和删除的工作是比较简单的.并且是Redis.Leve ...

  4. 4 tips for staying productive on Friday

    4 tips for staying productive on Friday如何让你的周五和周一一样有效率1.Schedule Your Day with Tasks 用任务计划一天 Sometim ...

  5. Log4J入门教程(二) 参数讲解

    继续接着Log4J入门教程(一)中的例子进行讲解,其中log4j.properties中的内容为    Log4j的三个重要组件—— Loggers, Appenders, Layouts ,这三个组 ...

  6. 虚拟机WindowServer2003共享文件夹

    前话 之前我写过虚拟机装SQL Server的博文,也许有同学参考了也通过虚拟机装数据库服务来做实验作业了. 到了第二章节学习时,实验要求数据库导出Excel文件,这样一来就出现了小问题了,Windo ...

  7. UML系列02之 UML类图(2)

    UML类图的几种关系 在UML类图中,关系可以分为4种: 泛化, 实现, 关联 和 依赖.1. 泛化 -- 表示"类与类之间的继承关系".2. 实现 -- 表示"类与接口 ...

  8. Android setStartOffset方法:设置启动时间

    [功能说明]该方法用于设置一个动画执行的启动时间,单位为毫秒.系统默认当执行start方法后立刻执行动画,当使用该方法设置后,将延迟一定的时间再启动动画. [基本语法]public void setS ...

  9. Eclipse中使用正则表达式搜索替换

    Eclipse中使用正则表达式搜索替换 分类:software | 标签: 正则表达  替换  eclipse  2011-11-29 11:28 阅读(1930)评论(0)编辑删除 最近在eclip ...

  10. c# ffmpeg视频转换

    c#  ffmpeg视频转换 什么是ffmpeg,它有什么作用呢,怎么可以使用它呢,带着问题去找答案吧!先参考百度百科把,我觉得它很强大无奇不有,为了方便大家我就把链接提供了! http://baik ...