久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Android消息處理探秘 .

 aaie_ 2012-09-05

下圖為Android消息處理機(jī)制順序圖:


由圖可知,,第一步通過調(diào)用Looper.prepare()來創(chuàng)建Looper和MessageQueue java對(duì)象,MessageQueue java類通過保存單向鏈表頭mMessages來遍歷所有消息,,注意此單向鏈表按時(shí)間順序從早到晚排列,,因此mMessages指向的消息總是為需最早處理的消息。在第5步創(chuàng)建C++ Looper對(duì)象,,在其中創(chuàng)建讀寫管道并通過epoll來監(jiān)控讀管道,。

第7步創(chuàng)建Handler給用戶使用,第8步在消息處理線程內(nèi)調(diào)用Looper.loop()來進(jìn)入消息處理循環(huán),,在10步取下一消息時(shí)調(diào)用nativePollOnce方法,,直到13步調(diào)到Looper.pollOnce(),在這里將等待管道POLLIN事件一定時(shí)間(timeoutMillis毫秒),,如果有事件則返回否則等待timeoutMillis毫秒。在第10步MessageQueue.next()取下一消息時(shí),,將無限循環(huán)直到得到消息,。循環(huán)時(shí)第一次傳的超時(shí)時(shí)間timeoutMillis=0,如果此時(shí)尚無消息,,則檢查是否有IdleHandler,如有則調(diào)用所有Handler并置Handler為空,,timeoutMillis設(shè)為0進(jìn)行第二次查詢, 以后timeoutMillis將設(shè)為-1,,因此線程將一直掛起,,直到有消息到來,。

  1. public class MessageQueue{  
  2.     final Message next() {  
  3.         int pendingIdleHandlerCount = -1// -1 only during first iteration   
  4.         int nextPollTimeoutMillis = 0//第一次立刻返回不等待   
  5.   
  6.         for (;;) {  
  7.             if (nextPollTimeoutMillis != 0) {  
  8.                 Binder.flushPendingCommands();  
  9.             }  
  10.             nativePollOnce(mPtr, nextPollTimeoutMillis); //第一次=0   
  11.   
  12.             synchronized (this) {  
  13.                 // Try to retrieve the next message.  Return if found.   
  14.                 final long now = SystemClock.uptimeMillis();  
  15.                 final Message msg = mMessages;  
  16.                 if (msg != null) {  
  17.                     final long when = msg.when;  
  18.                     if (now >= when) { //如果消息發(fā)送時(shí)間滿足   
  19.                         mBlocked = false;  
  20.                         mMessages = msg.next;  
  21.                         msg.next = null;  
  22.                         if (false) Log.v("MessageQueue""Returning message: " + msg);  
  23.                         msg.markInUse();  
  24.                         return msg;     //取消息成功   
  25.                     } else {  
  26.                         nextPollTimeoutMillis = (int) Math.min(when - now, Integer.MAX_VALUE); //如果有消息但消息尚未到達(dá)發(fā)送時(shí)間,,則以該時(shí)間到當(dāng)前時(shí)間的時(shí)間差作為下次查詢超時(shí)的時(shí)間   
  27.                     }  
  28.                 } else {  
  29.                     nextPollTimeoutMillis = -1;      //無限等待   
  30.                 }  
  31.   
  32.                 // If first time, then get the number of idlers to run.   
  33.                 if (pendingIdleHandlerCount < 0) {  
  34.                     pendingIdleHandlerCount = mIdleHandlers.size();  
  35.                 }  
  36.                 if (pendingIdleHandlerCount == 0) { //如果尚未設(shè)置IdleHandler   
  37.                     // No idle handlers to run.  Loop and wait some more.   
  38.                     mBlocked = true;  
  39.                     continue;  
  40.                 }  
  41.   
  42.                 if (mPendingIdleHandlers == null) {  
  43.                     mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];  
  44.                 }  
  45.                 mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);  
  46.             }  
  47.   
  48.             // Run the idle handlers.   
  49.             // We only ever reach this code block during the first iteration.   
  50.             for (int i = 0; i < pendingIdleHandlerCount; i++) {  
  51.                 final IdleHandler idler = mPendingIdleHandlers[i];  
  52.                 mPendingIdleHandlers[i] = null// release the reference to the handler   
  53.   
  54.                 boolean keep = false;  
  55.                 try {  
  56.                     keep = idler.queueIdle();  
  57.                 } catch (Throwable t) {  
  58.                     Log.wtf("MessageQueue""IdleHandler threw exception", t);  
  59.                 }  
  60.   
  61.                 if (!keep) {  
  62.                     synchronized (this) {  
  63.                         mIdleHandlers.remove(idler);  
  64.                     }  
  65.                 }  
  66.             }  
  67.   
  68.             // Reset the idle handler count to 0 so we do not run them again.   
  69.             pendingIdleHandlerCount = 0;  
  70.   
  71.             // While calling an idle handler, a new message could have been delivered   
  72.             // so go back and look again for a pending message without waiting.   
  73.             nextPollTimeoutMillis = 0;  
  74.         }  
  75.     }  


第17步用戶線程通過Handler發(fā)送消息,,在20步將調(diào)用nativeWake來喚醒消息處理線程,。最終第24步消息被處理。


  1. final boolean enqueueMessage(Message msg, long when) {  
  2.     if (msg.isInUse()) {  
  3.         throw new AndroidRuntimeException(msg  
  4.                 + " This message is already in use.");  
  5.     }  
  6.     if (msg.target == null && !mQuitAllowed) {  
  7.         throw new RuntimeException("Main thread not allowed to quit");  
  8.     }  
  9.     final boolean needWake;  
  10.     synchronized (this) {  
  11.         if (mQuiting) {  
  12.             RuntimeException e = new RuntimeException(  
  13.                 msg.target + " sending message to a Handler on a dead thread");  
  14.             return false;  
  15.         } else if (msg.target == null) {  
  16.             mQuiting = true;  
  17.         }  
  18.   
  19.         msg.when = when;  
  20.         Message p = mMessages;  
  21.         if (p == null || when == 0 || when < p.when) { //如果消息隊(duì)列為空或者當(dāng)前消息為發(fā)送時(shí)間最早的消息   
  22.             msg.next = p;  
  23.             mMessages = msg;  
  24.             needWake = mBlocked; // mBlocked=true表示線程已被掛起   
  25.         } else {  
  26.             Message prev = null;  
  27.             while (p != null && p.when <= when) {  
  28.                 prev = p;  
  29.                 p = p.next;  
  30.             }  
  31.             msg.next = prev.next;  
  32.             prev.next = msg;  
  33.             needWake = false// still waiting on head, no need to wake up   
  34.         }  
  35.     }  
  36.     if (needWake) {  
  37.         nativeWake(mPtr);        //喚醒線程   
  38.     }  
  39.     return true;  
  40. }  


MessageQueue java類單向鏈表:

  1. public final class Message implements Parcelable {  
  2.     Message next; //消息鏈表頭  


典型的消息處理代碼

  1. *  class LooperThread extends Thread {  
  2. *      public Handler mHandler;  
  3. *  
  4. *      public void run() {  
  5. *          Looper.prepare();      //創(chuàng)建Looper對(duì)象,,在Looper對(duì)象創(chuàng)建時(shí)將創(chuàng)建MessageQueue.最后將Looper對(duì)象存儲(chǔ)在線程局部變量中   
  6. *  
  7. *          mHandler = new Handler() { //創(chuàng)建Handler對(duì)象,,在此將讀取線程局部變量得到本線程的Looper對(duì)象及消息隊(duì)列   
  8. *              public void handleMessage(Message msg) {  
  9. *                  // process incoming messages here   
  10. *              }  
  11. *          };  
  12. *  
  13. *          Looper.loop(); //進(jìn)入Looper對(duì)象的消息處理循環(huán)   
  14. *      }  
  15. *  }  


用戶主要操作接口類Handler,可以通過重載handleMessage()方法實(shí)現(xiàn)自定義方法處理:


Handler.java

  1.     public void dispatchMessage(Message msg) {  
  2.         if (msg.callback != null) { //如果消息已設(shè)置callback,則調(diào)用該callback函數(shù)   
  3.             handleCallback(msg);  
  4.         } else {  
  5.             if (mCallback != null) { //如果Handler已設(shè)置callback,則調(diào)用該callback處理消息   
  6.                 if (mCallback.handleMessage(msg)) { //如果消息被處理   
  7.                     return;  
  8.                 }  
  9.             }  
  10.             handleMessage(msg); //默認(rèn)為空函數(shù),,用戶可重載處理自定義消息   
  11.         }  
  12.     }  
  13.     private final void handleCallback(Message message) {  
  14.         message.callback.run();  
  15.     }  
  16.     public Handler(Callback callback) {  
  17.         mLooper = Looper.myLooper(); //得到本線程的Looper對(duì)象   
  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 = callback;  
  24.     }  

用戶主要操作接口類Looper

frameworks/base/core/java/android/os/Looper.java

  1. public class Looper{  
  2.      /** Initialize the current thread as a looper. 
  3.       * This gives you a chance to create handlers that then reference 
  4.       * this looper, before actually starting the loop. Be sure to call 
  5.       * {@link #loop()} after calling this method, and end it by calling 
  6.       * {@link #quit()}. 
  7.       */  
  8.     public static void prepare() {  
  9.         if (sThreadLocal.get() != null) {  
  10.             throw new RuntimeException("Only one Looper may be created per thread");  
  11.         }  
  12.         sThreadLocal.set(new Looper());  
  13.     }  
  14.   
  15.     /** 
  16.      * Initialize the current thread as a looper, marking it as an 
  17.      * application's main looper. The main looper for your application 
  18.      * is created by the Android environment, so you should never need 
  19.      * to call this function yourself.  See also: {@link #prepare()} 
  20.      */  
  21.     public static void prepareMainLooper() {  
  22.         prepare();  
  23.         setMainLooper(myLooper());  
  24.         myLooper().mQueue.mQuitAllowed = false;  
  25.     }  
  26.   
  27.     public static void loop() {  
  28.         Looper me = myLooper();  
  29.         if (me == null) {  
  30.             throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");  
  31.         }  
  32.         MessageQueue queue = me.mQueue;  
  33.                   
  34.         while (true) {  
  35.             Message msg = queue.next(); // might block   
  36.             if (msg != null) {  
  37.                 if (msg.target == null) {  
  38.                     // No target is a magic identifier for the quit message.   
  39.                     return;  
  40.                 }  
  41.   
  42.                 long wallStart = 0;  
  43.                 long threadStart = 0;  
  44.   
  45.                 msg.target.dispatchMessage(msg); //處理消息   
  46.                 }                  
  47.                 msg.recycle();  
  48.             }  
  49.         }  
  50.     }  

問題:

1.為了實(shí)現(xiàn)消息隊(duì)列等待機(jī)制,采用epoll方式來實(shí)現(xiàn)來消息時(shí)消息隊(duì)列處理線程的喚醒和當(dāng)無消息時(shí)線程掛起。實(shí)際上如果采用java對(duì)象wait/notify來實(shí)現(xiàn)此種功能更為簡單,,難道還有別的因素導(dǎo)致Google采用目前的設(shè)計(jì),?

分析:估計(jì)與IdleHandler有關(guān),目前當(dāng)消息隊(duì)列首次為空或取完所有消息后,,如果注冊(cè)了IdleHandler則會(huì)調(diào)用這些Handler處理,然后才會(huì)無限等待下一個(gè)消息到來

2.跨進(jìn)程消息傳送如何實(shí)現(xiàn):如鼠標(biāo)鍵盤事件傳遞

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多