乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      Android消息處理探秘 .

       aaie_ 2012-09-05

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


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

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

      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í)間滿(mǎn)足   
      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í)間差作為下次查詢(xún)超時(shí)的時(shí)間   
      27.                     }  
      28.                 } else {  
      29.                     nextPollTimeoutMillis = -1;      //無(wú)限等待   
      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步用戶(hù)線(xiàn)程通過(guò)Handler發(fā)送消息,在20步將調(diào)用nativeWake來(lái)喚醒消息處理線(xiàn)程。最終第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表示線(xiàn)程已被掛起   
      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);        //喚醒線(xiàn)程   
      38.     }  
      39.     return true;  
      40. }  


      MessageQueue java類(lèi)單向鏈表:

      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ǔ)在線(xiàn)程局部變量中   
      6. *  
      7. *          mHandler = new Handler() { //創(chuàng)建Handler對(duì)象,在此將讀取線(xiàn)程局部變量得到本線(xiàn)程的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. *  }  


      用戶(hù)主要操作接口類(lèi)Handler,可以通過(guò)重載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ù),用戶(hù)可重載處理自定義消息   
      11.         }  
      12.     }  
      13.     private final void handleCallback(Message message) {  
      14.         message.callback.run();  
      15.     }  
      16.     public Handler(Callback callback) {  
      17.         mLooper = Looper.myLooper(); //得到本線(xiàn)程的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.     }  

      用戶(hù)主要操作接口類(lèi)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.     }  

      問(wèn)題:

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

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

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

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(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)遵守用戶(hù) 評(píng)論公約

        類(lèi)似文章 更多