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. }

看一下执行结果

  1. 04-30 07:17:58.754: V/MainActivity(597): loop以前的语句
  2. 04-30 07:17:58.784: V/MainActivity(597): 子线程收到主线程发来的消息
  3. 04-30 07:18:01.794: V/MainActivity(597): 主线程收到子线程发来的消息
  4. 04-30 07:18:01.794: V/MainActivity(597): thread.isAlive?true
  5. 04-30 07:18:04.804: V/MainActivity(597): 子线程收到主线程发来的消息
  6. 04-30 07:18:07.814: V/MainActivity(597): 主线程收到子线程发来的消息
  7. 04-30 07:18:07.814: V/MainActivity(597): thread.isAlive?true
  8. 04-30 07:18:08.780: V/MainActivity(597): 第三个子线程里面每隔10s判断 thread.isAlive?true
  9. 04-30 07:18:10.824: V/MainActivity(597): 子线程收到主线程发来的消息
  10. 04-30 07:18:13.834: V/MainActivity(597): 主线程收到子线程发来的消息
  11. 04-30 07:18:13.834: V/MainActivity(597): thread.isAlive?true
  12. 04-30 07:18:16.844: V/MainActivity(597): 子线程收到主线程发来的消息
  13. 04-30 07:18:18.782: V/MainActivity(597): 第三个子线程里面每隔10s判断 thread.isAlive?true
  14. 04-30 07:18:19.844: V/MainActivity(597): 主线程收到子线程发来的消息
  15. 04-30 07:18:19.844: V/MainActivity(597): thread.isAlive?true
  16. 04-30 07:18:22.854: V/MainActivity(597): 子线程收到主线程发来的消息
  17. 04-30 07:18:25.864: V/MainActivity(597): 主线程收到子线程发来的消息
  18. 04-30 07:18:25.864: V/MainActivity(597): now flagvalue is over 5
  19. 04-30 07:18:25.864: V/MainActivity(597): quit thread.isAlive?true
  20. 04-30 07:18:25.874: V/MainActivity(597): loop以后的语句
  21. 04-30 07:18:25.874: V/MainActivity(597): quit thread.isAlive?false
  22. 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行,

  1. 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. }

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

看一下日志

  1. 04-30 09:04:16.345: V/mainactivity(935): main onPreExecute
  2. 04-30 09:04:16.494: V/mainactivity(935): main onProgressUpdate
  3. 04-30 09:04:16.884: V/mainactivity(935): main onProgressUpdate
  4. 04-30 09:04:16.914: V/mainactivity(935): main onProgressUpdate
  5. 04-30 09:04:16.914: V/mainactivity(935): main onProgressUpdate
  6. 04-30 09:04:16.914: V/mainactivity(935): main onProgressUpdate
  7. 04-30 09:04:17.264: V/mainactivity(935): main onProgressUpdate
  8. 04-30 09:04:17.264: V/mainactivity(935): main onProgressUpdate
  9. 04-30 09:04:17.284: V/mainactivity(935): main onProgressUpdate
  10. 04-30 09:04:17.284: V/mainactivity(935): main onProgressUpdate
  11. 04-30 09:04:17.365: V/mainactivity(935): main onProgressUpdate
  12. 04-30 09:04:17.414: V/mainactivity(935): main onProgressUpdate
  13. 04-30 09:04:17.414: V/mainactivity(935): main onProgressUpdate
  14. 04-30 09:04:17.484: V/mainactivity(935): main onProgressUpdate
  15. 04-30 09:04:17.534: V/mainactivity(935): main onProgressUpdate
  16. 04-30 09:04:17.614: V/mainactivity(935): main onProgressUpdate
  17. 04-30 09:04:17.684: V/mainactivity(935): main onProgressUpdate
  18. 04-30 09:04:17.754: V/mainactivity(935): main onProgressUpdate
  19. 04-30 09:04:17.834: V/mainactivity(935): main onProgressUpdate
  20. 04-30 09:04:17.914: V/mainactivity(935): main onProgressUpdate
  21. 04-30 09:04:17.994: V/mainactivity(935): main onProgressUpdate
  22. 04-30 09:04:18.074: V/mainactivity(935): main onProgressUpdate
  23. 04-30 09:04:18.154: V/mainactivity(935): main onProgressUpdate
  24. 04-30 09:04:18.244: V/mainactivity(935): main onProgressUpdate
  25. 04-30 09:04:18.324: V/mainactivity(935): main onProgressUpdate
  26. 04-30 09:04:18.404: V/mainactivity(935): main onProgressUpdate
  27. 04-30 09:04:18.484: V/mainactivity(935): main onProgressUpdate
  28. 04-30 09:04:18.565: V/mainactivity(935): main onProgressUpdate
  29. 04-30 09:04:18.644: V/mainactivity(935): main onProgressUpdate
  30. 04-30 09:04:18.724: V/mainactivity(935): main onProgressUpdate
  31. 04-30 09:04:18.804: V/mainactivity(935): main onProgressUpdate
  32. 04-30 09:04:18.884: V/mainactivity(935): main onProgressUpdate
  33. 04-30 09:04:18.964: V/mainactivity(935): main onProgressUpdate
  34. 04-30 09:04:19.053: V/mainactivity(935): main onProgressUpdate
  35. 04-30 09:04:19.134: V/mainactivity(935): main onProgressUpdate
  36. 04-30 09:04:19.214: V/mainactivity(935): main onProgressUpdate
  37. 04-30 09:04:19.294: V/mainactivity(935): main onProgressUpdate
  38. 04-30 09:04:19.375: V/mainactivity(935): main onProgressUpdate
  39. 04-30 09:04:19.454: V/mainactivity(935): main onProgressUpdate
  40. 04-30 09:04:19.534: V/mainactivity(935): main onProgressUpdate
  41. 04-30 09:04:19.614: V/mainactivity(935): main onProgressUpdate
  42. 04-30 09:04:19.694: V/mainactivity(935): main onProgressUpdate
  43. 04-30 09:04:19.784: V/mainactivity(935): main onProgressUpdate
  44. 04-30 09:04:19.864: V/mainactivity(935): main onProgressUpdate
  45. 04-30 09:04:19.944: V/mainactivity(935): main onProgressUpdate
  46. 04-30 09:04:20.024: V/mainactivity(935): main onProgressUpdate
  47. 04-30 09:04:20.104: V/mainactivity(935): main onProgressUpdate
  48. 04-30 09:04:20.184: V/mainactivity(935): main onProgressUpdate
  49. 04-30 09:04:20.264: V/mainactivity(935): main onProgressUpdate
  50. 04-30 09:04:20.344: V/mainactivity(935): main onProgressUpdate
  51. 04-30 09:04:20.425: V/mainactivity(935): main onProgressUpdate
  52. 04-30 09:04:20.504: V/mainactivity(935): main onProgressUpdate
  53. 04-30 09:04:20.593: V/mainactivity(935): main onProgressUpdate
  54. 04-30 09:04:20.674: V/mainactivity(935): main onProgressUpdate
  55. 04-30 09:04:20.754: V/mainactivity(935): main onProgressUpdate
  56. 04-30 09:04:20.834: V/mainactivity(935): main onProgressUpdate
  57. 04-30 09:04:20.914: V/mainactivity(935): main onProgressUpdate
  58. 04-30 09:04:20.994: V/mainactivity(935): main onProgressUpdate
  59. 04-30 09:04:21.073: V/mainactivity(935): main onProgressUpdate
  60. 04-30 09:04:21.154: V/mainactivity(935): main onProgressUpdate
  61. 04-30 09:04:21.233: V/mainactivity(935): main onProgressUpdate
  62. 04-30 09:04:21.313: V/mainactivity(935): main onProgressUpdate
  63. 04-30 09:04:21.404: V/mainactivity(935): main onProgressUpdate
  64. 04-30 09:04:21.485: V/mainactivity(935): main onProgressUpdate
  65. 04-30 09:04:21.563: V/mainactivity(935): main onProgressUpdate
  66. 04-30 09:04:21.643: V/mainactivity(935): main onProgressUpdate
  67. 04-30 09:04:21.723: V/mainactivity(935): main onProgressUpdate
  68. 04-30 09:04:21.803: V/mainactivity(935): main onProgressUpdate
  69. 04-30 09:04:21.883: V/mainactivity(935): main onProgressUpdate
  70. 04-30 09:04:21.963: V/mainactivity(935): main onProgressUpdate
  71. 04-30 09:04:22.043: V/mainactivity(935): main onProgressUpdate
  72. 04-30 09:04:22.123: V/mainactivity(935): main onProgressUpdate
  73. 04-30 09:04:22.204: V/mainactivity(935): main onProgressUpdate
  74. 04-30 09:04:22.293: V/mainactivity(935): main onProgressUpdate
  75. 04-30 09:04:22.373: V/mainactivity(935): main onProgressUpdate
  76. 04-30 09:04:22.454: V/mainactivity(935): main onProgressUpdate
  77. 04-30 09:04:22.533: V/mainactivity(935): main onProgressUpdate
  78. 04-30 09:04:22.613: V/mainactivity(935): main onProgressUpdate
  79. 04-30 09:04:22.693: V/mainactivity(935): main onProgressUpdate
  80. 04-30 09:04:22.773: V/mainactivity(935): main onProgressUpdate
  81. 04-30 09:04:22.854: V/mainactivity(935): main onProgressUpdate
  82. 04-30 09:04:22.934: V/mainactivity(935): main onProgressUpdate
  83. 04-30 09:04:23.024: V/mainactivity(935): main onProgressUpdate
  84. 04-30 09:04:23.103: V/mainactivity(935): main onProgressUpdate
  85. 04-30 09:04:23.184: V/mainactivity(935): main onProgressUpdate
  86. 04-30 09:04:23.264: V/mainactivity(935): main onProgressUpdate
  87. 04-30 09:04:23.344: V/mainactivity(935): main onProgressUpdate
  88. 04-30 09:04:23.424: V/mainactivity(935): main onProgressUpdate
  89. 04-30 09:04:23.504: V/mainactivity(935): main onProgressUpdate
  90. 04-30 09:04:23.584: V/mainactivity(935): main onProgressUpdate
  91. 04-30 09:04:23.664: V/mainactivity(935): main onProgressUpdate
  92. 04-30 09:04:23.744: V/mainactivity(935): main onProgressUpdate
  93. 04-30 09:04:23.834: V/mainactivity(935): main onProgressUpdate
  94. 04-30 09:04:23.914: V/mainactivity(935): main onProgressUpdate
  95. 04-30 09:04:23.994: V/mainactivity(935): main onProgressUpdate
  96. 04-30 09:04:24.074: V/mainactivity(935): main onProgressUpdate
  97. 04-30 09:04:24.154: V/mainactivity(935): main onProgressUpdate
  98. 04-30 09:04:24.234: V/mainactivity(935): main onProgressUpdate
  99. 04-30 09:04:24.314: V/mainactivity(935): main onProgressUpdate
  100. 04-30 09:04:24.394: V/mainactivity(935): main onProgressUpdate
  101. 04-30 09:04:24.474: V/mainactivity(935): AsyncTask #5 doInBackground
  102. 04-30 09:04:24.474: V/mainactivity(935): main onProgressUpdate

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

  1. AsyncTask
  2.  
  3. 的执行周期 以及那些方法都是在哪个线程执行的(ui还是子?)
  4.  
  5. 然后 我们就来分析一下 这个AsyncTask类到底是怎么做的?
  6.  
  7. 这是我们调用的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方法 只能执行一次,不然就要抛异常。同时 也能看出来

  1. onPreExecute(); 这个方法是在主线程执行的。
  2.  
  3. 然后我们着重看一下19行,这个地方,mWorker 是什么?
  4.  
  5. 找了一下 发现
  1. private final WorkerRunnable<Params, Result> mWorker;

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

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

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

  1. Callable 这个接口
  2.  
  3. 当然了 因为这是抽象类,所以我们无需实现这个接口。
  4.  
  5. 既然
  1. 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. }
  1. 到这 我们相信 mWorker大家已经知道是怎么回事了 5-12行表明了mWorker 是一个对象,并且他的回调方法里面 也调用了
  1. doInBackground 这个方法,至与
  1. postResult 这个方法 我们可以等会再看,先往下面继续看,我们再拿到
  1. mWorker 这个对象以后 又利用他 去初始化了
  1. mFuture 这个对象,且这个对象是由
  1. FutureTask 这个类生成的,哪我们就去看看这个类。
  1. public class FutureTask<V> implements RunnableFuture<V> {

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

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

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

回到excute方法

我们发现了 这句话

exec.execute(mFuture);

实际上 就是这么调用的

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

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

  1. private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;

再看看

SERIAL_EXECUTOR 这是什么?

  1. /**
  2. * An {@link Executor} that executes tasks one at a time in serial
  3. * order. This serialization is global to a particular process.
  4. */
  5. 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.  
  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;
  1. private static final BlockingQueue<Runnable> sPoolWorkQueue =
  2. new LinkedBlockingQueue<Runnable>(10);

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

但实际上我们回到

  1. SerialExecutor
  2.  
  3. 这个类的5=15
  4.  
  5. 我们发现 实际上我们还是从队列里面取任务出来做,任务做完了,才去取下一个任务。
  6.  
  7. 所以 AsyncTask 他本质上还是一个单线程执行的 东西,(当然执行的时候是在子线程 而不是主线程执行的)
  8.  
  9. 我们再回到一开始的地方
  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方法实际执行的是

  1. 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. }
  1. 所以线程中执行的是3-8行里的代码!!!!!!!!!!!!!!!!!!!!!!!!!!
  2.  
  3. 所以doInBackground 这方法是在子线程里面去执行的。
  4.  
  5. 执行完毕以后才调用了下面的方法
  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. }
  1. 于是 整个AsyncTask的生命周期 就全部得到印证,执行顺序 到这里也就差不多了。
  2.  
  3. 至此 我们 AsyncTaskLooper,Handler 这三者的源码分析 也就告一段落。
  1.  
  1.  
  1.  

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

正确理解 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. JS初学的一些易错的知识点

    1.  false ,0 , "" ,undefined , null  在Boolean 环境下当成 false: null  在数值环境下当成 0: undefined 在数值 ...

  2. 【XJOI-NOIP16提高模拟训练9】题解。

    http://www.hzxjhs.com:83/contest/55 说实话这次比赛真的很水..然而我只拿了140分,面壁反思. 第一题: 发现数位和sum最大就是9*18,k最大1000,那么su ...

  3. SSH连接不上Linux的解决方法

    SSH连接不上Linux的解决方法: 连续弄了几次,今天早上终于把SSH连接虚拟机连接不通的问题解决了. 先简单说下概要: 主机装的是XP系统,虚拟机用的是red hat Linux. 我用的是nat ...

  4. JavaWeb笔记——Jsp的指令、内置对象和动作标签

    JSP三大指令   一个jsp页面中,可以有0~N个指令的定义! 1. page --> 最复杂:<%@page language="java" info=" ...

  5. CentOS7安装配置Apache HTTP Server

    RPM安装httpd 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 # yum -yinstall http ...

  6. .NET单例模式-------各种写法&&验证

    .NET单例模式-------各种写法&&验证 前言 单例模式对大家来说都不陌生,也很容易搞懂其原理,本篇文章也不提供单例模式的详细原理解析,本篇文章的目的是展示在C#中单例模式的各种 ...

  7. USACO Section 3.3: Riding the Fences

    典型的找欧拉路径的题.先贴下USACO上找欧拉路径的法子: Pick a starting node and recurse on that node. At each step: If the no ...

  8. URAL 1233 Amusing Numbers 好题

    参照了nocow上的解法,照搬过来…… 易知一个数X在数列中在另一个数Y前,当且仅当X前缀小于Y或前缀相等X短,那么我们分布考虑,比如对于数48561: 5位上:10000~48560; 4位上:10 ...

  9. ajax练习习题三搜索

    做一个汽车搜索页面 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://w ...

  10. 无开发经验,初学python

    1.无开发经验,初学python   如果你不会其他语言,python是你的第一门语言: A Byte of Python (简明python教程,这个有中文版简明 Python 教程)是非常好的入门 ...