zoukankan      html  css  js  c++  java
  • 正确理解 AsyncTask,Looper,Handler三者之间的关系(基于android 4.0)

    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 这三者的源码分析 也就告一段落。






     

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

  • 相关阅读:
    HTML5实现大文件分片上传教程
    HTML5实现大文件分片上传方案
    HTML5实现大文件分片上传技术
    HTML5实现大文件分片上传实例解析
    IfcRepresentationMap——Mapped shape with transformation
    UWB基站地图数据
    IfcRepresentationMap—Mapped shape without transformation
    Exception
    【官网链接】 REPRODUCIBILITY —— pytorch的可复现性
    【转载】 pytorch reproducibility —— pytorch代码的可复现性
  • 原文地址:https://www.cnblogs.com/punkisnotdead/p/4469612.html
Copyright © 2011-2022 走看看