正確理解 AsyncTask,Looper,Handler三者之間的關係(基於android 4.0)

希爾瓦娜斯女神發表於2015-04-30

Looper 和Handler 是理解好AsyncTask的一個基礎,我們可以先從這裡開始,先給出一個主執行緒和子執行緒互相通訊的例子。

  1 package com.example.loopertest;
  2 
  3 import android.app.Activity;
  4 import android.os.Bundle;
  5 import android.os.Handler;
  6 import android.os.Looper;
  7 import android.os.Message;
  8 import android.util.Log;
  9 
 10 public class MainActivity extends Activity {
 11 
 12     public static final int SIGNAL_1 = 0x1;
 13     public static final int SIGNAL_2 = 0x2;
 14 
 15     public static int flagValue = 0;
 16     private LooperThread thread;
 17     private Handler uiHandler = new Handler() {
 18         @Override
 19         public void handleMessage(Message msg) {
 20             // TODO Auto-generated method stub
 21             switch (msg.what) {
 22             case SIGNAL_1:
 23                 Log.v("MainActivity", "主執行緒收到子執行緒發來的訊息");
 24                 flagValue++;
 25                 if (flagValue == 5) {
 26                     Log.v("MainActivity", "now flagvalue is over 5");
 27                     Log.v("MainActivity",
 28                             "quit 前 thread.isAlive?" + thread.isAlive());
 29                     thread.cHandler.getLooper().quit();
 30                     Log.v("MainActivity",
 31                             "quit 後 thread.isAlive?" + thread.isAlive());
 32                 } else {
 33                     Log.v("MainActivity", "thread.isAlive?" + thread.isAlive());
 34                     thread.cHandler.sendEmptyMessageDelayed(SIGNAL_1, 3000);
 35                 }
 36                 break;
 37             case SIGNAL_2:
 38                 thread.cHandler.sendEmptyMessage(SIGNAL_1);
 39                 break;
 40             default:
 41                 break;
 42             }
 43         }
 44     };
 45 
 46     @Override
 47     protected void onCreate(Bundle savedInstanceState) {
 48         super.onCreate(savedInstanceState);
 49         setContentView(R.layout.activity_main);
 50 
 51         thread = new LooperThread();
 52         thread.start();
 53         uiHandler.sendEmptyMessage(SIGNAL_2);
 54 
 55         new Thread() {
 56             public void run() {
 57                 while (true) {
 58                     try {
 59                         Thread.sleep(10000);
 60                     } catch (InterruptedException e) {
 61                         // TODO Auto-generated catch block
 62                         e.printStackTrace();
 63                     }
 64                     Log.v("MainActivity",
 65                             "第三個子執行緒裡面每隔10s判斷 thread.isAlive?"
 66                                     + thread.isAlive());
 67                 }
 68             }
 69         }.start();
 70 
 71     }
 72 
 73     class LooperThread extends Thread {
 74         public Handler cHandler;
 75 
 76         @Override
 77         public void run() {
 78 
 79             // 例項化messagequeue
 80             Looper.prepare();
 81 
 82             cHandler = new Handler() {
 83                 @Override
 84                 public void handleMessage(Message msg) {
 85                     // TODO Auto-generated method stub
 86                     switch (msg.what) {
 87                     case SIGNAL_1:
 88                         Log.v("MainActivity", "子執行緒收到主執行緒發來的訊息");
 89                         uiHandler.sendEmptyMessageDelayed(SIGNAL_1, 3000);
 90                         break;
 91                     default:
 92                         break;
 93                     }
 94                 }
 95             };
 96             Log.v("MainActivity", "loop以前的語句");
 97             Looper.loop();
 98 
 99             Log.v("MainActivity", "loop以後的語句");
100 
101         }
102 
103     }
104 
105 }

看一下執行結果

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(); 這句話,我們來看一下原始碼是怎麼寫的,

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

一下就能看出來 如果get()的值不是空 那麼就要丟擲這個異常,這樣就能解釋我們一個執行緒 肯定只能有一個looper了,並且Looper.prepare() 在一個執行緒裡面只能呼叫一次,否則也要拋異常。

當然了 我們可以點到這個set方法裡面看一下 大概做了什麼操作。

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

然後我們進入threadlocal這個類裡面的set方法看看。

 1 /**
 2      * Sets the value of this variable for the current thread. If set to
 3      * {@code null}, the value will be set to null and the underlying entry will
 4      * still be present.
 5      *
 6      * @param value the new value of the variable for the caller thread.
 7      */
 8     public void set(T value) {
 9         Thread currentThread = Thread.currentThread();
10         Values values = values(currentThread);
11         if (values == null) {
12             values = initializeValues(currentThread);
13         }
14         values.put(this, value);
15     }

到這個地方就很明顯了 看第9行,

 Thread currentThread = Thread.currentThread();

這也就是為什麼說一個執行緒只能有一個looper。也能說明Looper和執行緒的繫結 就是在這個方法裡面完成的。有興趣的同學還可以繼續看values這個內部類,我們在這裡先不去挖的太深。

說完prepare 方法 我們再說說loop方法,因為有很多人都不明白 為什麼loop方法以後的語句 都不執行。我們還是直接上原始碼。

 1  /**
 2      * Run the message queue in this thread. Be sure to call
 3      * {@link #quit()} to end the loop.
 4      */
 5     public static void loop() {
 6         Looper me = myLooper();
 7         if (me == null) {
 8             throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
 9         }
10         MessageQueue queue = me.mQueue;
11         
12         // Make sure the identity of this thread is that of the local process,
13         // and keep track of what that identity token actually is.
14         Binder.clearCallingIdentity();
15         final long ident = Binder.clearCallingIdentity();
16         
17         while (true) {
18             Message msg = queue.next(); // might block
19             if (msg != null) {
20                 if (msg.target == null) {
21                     // No target is a magic identifier for the quit message.
22                     return;
23                 }
24 
25                 long wallStart = 0;
26                 long threadStart = 0;
27 
28                 // This must be in a local variable, in case a UI event sets the logger
29                 Printer logging = me.mLogging;
30                 if (logging != null) {
31                     logging.println(">>>>> Dispatching to " + msg.target + " " +
32                             msg.callback + ": " + msg.what);
33                     wallStart = SystemClock.currentTimeMicro();
34                     threadStart = SystemClock.currentThreadTimeMicro();
35                 }
36 
37                 msg.target.dispatchMessage(msg);
38 
39                 if (logging != null) {
40                     long wallTime = SystemClock.currentTimeMicro() - wallStart;
41                     long threadTime = SystemClock.currentThreadTimeMicro() - threadStart;
42 
43                     logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
44                     if (logging instanceof Profiler) {
45                         ((Profiler) logging).profile(msg, wallStart, wallTime,
46                                 threadStart, threadTime);
47                     }
48                 }
49 
50                 // Make sure that during the course of dispatching the
51                 // identity of the thread wasn't corrupted.
52                 final long newIdent = Binder.clearCallingIdentity();
53                 if (ident != newIdent) {
54                     Log.wtf(TAG, "Thread identity changed from 0x"
55                             + Long.toHexString(ident) + " to 0x"
56                             + Long.toHexString(newIdent) + " while dispatching to "
57                             + msg.target.getClass().getName() + " "
58                             + msg.callback + " what=" + msg.what);
59                 }
60                 
61                 msg.recycle();
62             }
63         }
64     }

 

6-10行 我們能看出來 是取得了 looper的 訊息佇列,然後17行開始 就是一個while true迴圈了!這也就能解釋為啥loop方法一呼叫我們loop後面的程式碼就不會執行,

 

18行也能看出來,程式碼告訴我們是不斷的在訊息佇列裡面取訊息,並且有可能會阻塞~

 

我們再來看一下這個37行的程式碼

msg.target.dispatchMessage(msg);

 

到這個地方 可能很多人就能猜到了,這個地方就是我們處理訊息的地方。那麼這個msg.target我們應該怎麼理解?(很多人無法理解looper handler 之間的關係 其實是因為這個地方始終理解不了)

 

我們可以先放一放,先去看我們handler的程式碼,在我們文中開頭的第一個例子中,我們在prepare()以後 就建立了一個handler,

我們去看看handler的建構函式。

 

 1  /**
 2      * Default constructor associates this handler with the queue for the
 3      * current thread.
 4      *
 5      * If there isn't one, this handler won't be able to receive messages.
 6      */
 7     public Handler() {
 8         if (FIND_POTENTIAL_LEAKS) {
 9             final Class<? extends Handler> klass = getClass();
10             if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
11                     (klass.getModifiers() & Modifier.STATIC) == 0) {
12                 Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
13                     klass.getCanonicalName());
14             }
15         }
16 
17         mLooper = Looper.myLooper();
18         if (mLooper == null) {
19             throw new RuntimeException(
20                 "Can't create handler inside thread that has not called Looper.prepare()");
21         }
22         mQueue = mLooper.mQueue;
23         mCallback = null;
24     }

17-21行 可以看出來,我們在呼叫handler的建構函式的時候,會先取當前執行緒的looper 如果取不到就會報異常了~~

然後我們發訊息的時候是呼叫的send函式,

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

經過一番調查,我們發現最終都是呼叫的這個方法

 1 /**
 2      * Enqueue a message into the message queue after all pending messages
 3      * before the absolute time (in milliseconds) <var>uptimeMillis</var>.
 4      * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b>
 5      * You will receive it in {@link #handleMessage}, in the thread attached
 6      * to this handler.
 7      * 
 8      * @param uptimeMillis The absolute time at which the message should be
 9      *         delivered, using the
10      *         {@link android.os.SystemClock#uptimeMillis} time-base.
11      *         
12      * @return Returns true if the message was successfully placed in to the 
13      *         message queue.  Returns false on failure, usually because the
14      *         looper processing the message queue is exiting.  Note that a
15      *         result of true does not mean the message will be processed -- if
16      *         the looper is quit before the delivery time of the message
17      *         occurs then the message will be dropped.
18      */
19     public boolean sendMessageAtTime(Message msg, long uptimeMillis)
20     {
21         boolean sent = false;
22         MessageQueue queue = mQueue;
23         if (queue != null) {
24             msg.target = this;
25             sent = queue.enqueueMessage(msg, uptimeMillis);
26         }
27         else {
28             RuntimeException e = new RuntimeException(
29                 this + " sendMessageAtTime() called with no mQueue");
30             Log.w("Looper", e.getMessage(), e);
31         }
32         return sent;
33     }

注意看 24行,

msg.target = this;

然後我們回到loop方法裡面 

msg.target.dispatchMessage(msg);

一下就能看出來,其實target就是handler。

 

所以loop方法裡面處理訊息實際上就是呼叫的handler的dispatchMessage 這個方法!

 

我們進去看這個方法

 

 1 /**
 2      * Handle system messages here.
 3      */
 4     public void dispatchMessage(Message msg) {
 5         if (msg.callback != null) {
 6             handleCallback(msg);
 7         } else {
 8             if (mCallback != null) {
 9                 if (mCallback.handleMessage(msg)) {
10                     return;
11                 }
12             }
13             handleMessage(msg);
14         }
15     }

 

看14行,發現其實呼叫的是handler的這個方法

1  /**
2      * Subclasses must implement this to receive messages.
3      */
4     public void handleMessage(Message msg) {
5     }

而這個方法 也是我們每次都去重寫的。到這裡 我們就算是理清楚了 handler 和looper 之間訊息傳遞的一個過程。

 

其實就是 先呼叫looper.prepare() 然後才能建立handler. 一個執行緒只能有一個looper 一個執行緒佇列 messagequeue.

handler發訊息的時候 發message的時候 實際上是把自己(handler本身)放在了message的 target變數裡面,這樣在loop

方法裡面無線迴圈的時候 我們才能回撥到 handler的handleMessage方法~~~~

 

同樣的我們也可以分析一下 為什麼quit方法 可以讓loop迴圈結束?(我就不分析了 留給大家自己分析 其實也是不難的)

 

搞清楚looper和handler的關係以後 我們就可以看看 AsyncTask這個東西。

 

 1 package com.example.asynctest;
 2 
 3 import android.app.Activity;
 4 import android.app.ProgressDialog;
 5 import android.os.AsyncTask;
 6 import android.os.Bundle;
 7 import android.os.Handler;
 8 import android.os.Looper;
 9 import android.util.Log;
10 import android.widget.TextView;
11 
12 public class MainActivity extends Activity {
13 
14     private TextView tv1;
15 
16     @Override
17     protected void onCreate(Bundle savedInstanceState) {
18         super.onCreate(savedInstanceState);
19         setContentView(R.layout.activity_main);
20         tv1 = (TextView) this.findViewById(R.id.tv1);
21         /**
22          * Task的例項必須在UI thread中建立; execute方法必須在UI thread中呼叫;
23          * 不要手動的呼叫onPreExecute(),
24          * onPostExecute(Result),doInBackground(Params...),
25          * onProgressUpdate(Progress...)這幾個方法; 該task只能被執行一次,否則多次呼叫時將會出現異常;
26          */
27         new MyAsyncTask().execute();
28 
29     }
30 
31     private class MyAsyncTask extends AsyncTask<Void, Integer, Void> {
32 
33         @Override
34         protected void onPreExecute() {
35             // TODO Auto-generated method stub
36             Log.v("mainactivity", Thread.currentThread().getName()
37                     + " onPreExecute ");
38         }
39 
40         /**
41          * 這裡不能直接操作ui 因為不是在主執行緒裡操作的
42          */
43         @Override
44         protected Void doInBackground(Void... params) {
45             // TODO Auto-generated method stub
46             // 模擬資料的載入,耗時的任務
47             for (int i = 0; i < 100; i++) {
48                 try {
49                     Thread.sleep(80);
50                 } catch (InterruptedException e) {
51                     e.printStackTrace();
52                 }
53                 publishProgress(i);
54             }
55 
56             Log.v("mainactivity", Thread.currentThread().getName()
57                     + " doInBackground ");
58             return null;
59         }
60 
61         /**
62          * 在主執行緒執行
63          */
64         @Override
65         protected void onProgressUpdate(Integer... values) {
66             tv1.setText(values[0] + "");
67             Log.v("mainactivity", Thread.currentThread().getName()
68                     + " onProgressUpdate ");
69         }
70 
71         /**
72          * 可以操作ui
73          */
74         @Override
75         protected void onPostExecute(Void result) {
76             // 進行資料載入完成後的UI操作
77             tv1.setText("LOAD DATA SUCCESS ");
78             Log.e("mainactivity", Thread.currentThread().getName()
79                     + " onPostExecute ");
80         }
81     }
82 
83 }

我們看一下 日誌和執行效果。

 

看一下日誌

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方法,
1 public final AsyncTask<Params, Progress, Result> execute(Params... params) {
2         return executeOnExecutor(sDefaultExecutor, params);
3     }

跟進去 看看。

 

 1 public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
 2             Params... params) {
 3         if (mStatus != Status.PENDING) {
 4             switch (mStatus) {
 5                 case RUNNING:
 6                     throw new IllegalStateException("Cannot execute task:"
 7                             + " the task is already running.");
 8                 case FINISHED:
 9                     throw new IllegalStateException("Cannot execute task:"
10                             + " the task has already been executed "
11                             + "(a task can be executed only once)");
12             }
13         }
14 
15         mStatus = Status.RUNNING;
16 
17         onPreExecute();
18 
19         mWorker.mParams = params;
20         exec.execute(mFuture);
21 
22         return this;
23     }

3-13行 我們可以看出來,這個excute方法 只能執行一次,不然就要拋異常。同時 也能看出來

onPreExecute(); 這個方法是在主執行緒執行的。

然後我們著重看一下19行,這個地方,mWorker 是什麼?

找了一下 發現

1     private final WorkerRunnable<Params, Result> mWorker;

實際上 是Workerrunnable這個類的物件,我們進去看看這個類。

 

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

發現這是一個靜態的抽象類~並且繼承了 

Callable 這個介面

當然了 因為這是抽象類,所以我們無需實現這個介面。

既然
mWorker  是 WorkerRunnable 他的物件,哪我們去看看 是如何new出來的呢?看構造方法

 1 /**
 2      * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
 3      */
 4     public AsyncTask() {
 5         mWorker = new WorkerRunnable<Params, Result>() {
 6             public Result call() throws Exception {
 7                 mTaskInvoked.set(true);
 8 
 9                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
10                 return postResult(doInBackground(mParams));
11             }
12         };
13 
14         mFuture = new FutureTask<Result>(mWorker) {
15             @Override
16             protected void done() {
17                 try {
18                     final Result result = get();
19 
20                     postResultIfNotInvoked(result);
21                 } catch (InterruptedException e) {
22                     android.util.Log.w(LOG_TAG, e);
23                 } catch (ExecutionException e) {
24                     throw new RuntimeException("An error occured while executing doInBackground()",
25                             e.getCause());
26                 } catch (CancellationException e) {
27                     postResultIfNotInvoked(null);
28                 } catch (Throwable t) {
29                     throw new RuntimeException("An error occured while executing "
30                             + "doInBackground()", t);
31                 }
32             }
33         };
34     }

 

到這 我們相信 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 這個類生成的,哪我們趕緊去看一下這個類,

 

 1 private static class SerialExecutor implements Executor {
 2         final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
 3         Runnable mActive;
 4 
 5         public synchronized void execute(final Runnable r) {
 6             mTasks.offer(new Runnable() {
 7                 public void run() {
 8                     try {
 9                         r.run();
10                     } finally {
11                         scheduleNext();
12                     }
13                 }
14             });
15             if (mActive == null) {
16                 scheduleNext();
17             }
18         }
19 
20         protected synchronized void scheduleNext() {
21             if ((mActive = mTasks.poll()) != null) {
22                 THREAD_POOL_EXECUTOR.execute(mActive);
23             }
24         }
25     }

第二行 明顯的 是建立了一個執行緒佇列

當執行excute方法的時候 

 

實際上就是把這個runnable 先放到執行緒佇列裡面,然後再去執行執行緒佇列裡的第一個執行緒,

 

20-24行 就是從這個執行緒佇列裡面取值,如果能取到 就執行這句話

 

THREAD_POOL_EXECUTOR.execute(mActive);

而THREAD_POOL_EXECUTOR就是一個執行緒池。

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

也可以看一下這個常量


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

 

有興趣的可以看下這個執行緒池的引數設定。

 

但實際上我們回到 

SerialExecutor 

這個類的5=15行

我們發現 實際上我們還是從佇列裡面取任務出來做,任務做完了,才去取下一個任務。

所以 AsyncTask 他本質上還是一個單執行緒執行的 東西,(當然執行的時候是在子執行緒 而不是主執行緒執行的)


我們再回到一開始的地方
 1 public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
 2             Params... params) {
 3         if (mStatus != Status.PENDING) {
 4             switch (mStatus) {
 5                 case RUNNING:
 6                     throw new IllegalStateException("Cannot execute task:"
 7                             + " the task is already running.");
 8                 case FINISHED:
 9                     throw new IllegalStateException("Cannot execute task:"
10                             + " the task has already been executed "
11                             + "(a task can be executed only once)");
12             }
13         }
14 
15         mStatus = Status.RUNNING;
16 
17         onPreExecute();
18 
19         mWorker.mParams = params;
20         exec.execute(mFuture);
21 
22         return this;
23     }

實際上我們執行的 就是mFuture 這個任務,這個任務在子執行緒裡面被執行。

 

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

 

1 /**
2      * Sets this Future to the result of its computation
3      * unless it has been cancelled.
4      */
5     public void run() {
6         sync.innerRun();
7     }

 

找到run方法

 

 1  void innerRun() {
 2             if (!compareAndSetState(READY, RUNNING))
 3                 return;
 4 
 5             runner = Thread.currentThread();
 6             if (getState() == RUNNING) { // recheck after setting thread
 7                 V result;
 8                 try {
 9                     result = callable.call();
10                 } catch (Throwable ex) {
11                     setException(ex);
12                     return;
13                 }
14                 set(result);
15             } else {
16                 releaseShared(0); // cancel
17             }
18         }

 

可以看出來 run方法實際執行的是 

callable.call 這個方法,所謂這個方法 不過也是我們一開始建構函式裡的mWorker物件罷了,

 1   public AsyncTask() {
 2         mWorker = new WorkerRunnable<Params, Result>() {
 3             public Result call() throws Exception {
 4                 mTaskInvoked.set(true);
 5 
 6                 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
 7                 return postResult(doInBackground(mParams));
 8             }
 9         };
10 
11         mFuture = new FutureTask<Result>(mWorker) {
12             @Override
13             protected void done() {
14                 try {
15                     final Result result = get();
16 
17                     postResultIfNotInvoked(result);
18                 } catch (InterruptedException e) {
19                     android.util.Log.w(LOG_TAG, e);
20                 } catch (ExecutionException e) {
21                     throw new RuntimeException("An error occured while executing doInBackground()",
22                             e.getCause());
23                 } catch (CancellationException e) {
24                     postResultIfNotInvoked(null);
25                 } catch (Throwable t) {
26                     throw new RuntimeException("An error occured while executing "
27                             + "doInBackground()", t);
28                 }
29             }
30         };
31     }

 

所以執行緒中執行的是3-8行裡的程式碼!!!!!!!!!!!!!!!!!!!!!!!!!!

所以doInBackground 這方法是在子執行緒裡面去執行的。

執行完畢以後才呼叫了下面的方法

1 private Result postResult(Result result) {
2         Message message = sHandler.obtainMessage(MESSAGE_POST_RESULT,
3                 new AsyncTaskResult<Result>(this, result));
4         message.sendToTarget();
5         return result;
6     }

最終我們找到這個handler裡面看一下 看看這裡面做了什麼。

 1 private static class InternalHandler extends Handler {
 2         @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
 3         @Override
 4         public void handleMessage(Message msg) {
 5             AsyncTaskResult result = (AsyncTaskResult) msg.obj;
 6             switch (msg.what) {
 7                 case MESSAGE_POST_RESULT:
 8                     // There is only one result
 9                     result.mTask.finish(result.mData[0]);
10                     break;
11                 case MESSAGE_POST_PROGRESS:
12                     result.mTask.onProgressUpdate(result.mData);
13                     break;
14             }
15         }
16     }

再看看這個finish方法

 

1  private void finish(Result result) {
2         if (isCancelled()) {
3             onCancelled(result);
4         } else {
5             onPostExecute(result);
6         }
7         mStatus = Status.FINISHED;
8     }
於是 整個AsyncTask的生命週期 就全部得到印證,執行順序 到這裡也就差不多了。

至此 我們 AsyncTask,Looper,Handler 這三者的原始碼分析 也就告一段落。

 

 

 





 



 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

---恢復內容結束---

相關文章