日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國內(nèi)最全I(xiàn)T社區(qū)平臺 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁 > php開源 > 綜合技術(shù) > Android中異步消息處理機(jī)制

Android中異步消息處理機(jī)制

來源:程序員人生   發(fā)布時(shí)間:2015-04-03 08:33:23 閱讀次數(shù):2918次


1. Thread Local Storage (線程局部存儲)

     我們通過位于android.os包下的Looper.class源碼可以看到成員變量區(qū)有1個(gè)線程局部變量sThreadLocal,該類的作用是線程局部存儲?那末是線程局部存儲TLS?這個(gè)問題可以從變量作用域的角度來理解。
     
     變量的常見作用域1般包括以下幾種。
  • 函數(shù)內(nèi)部變量。其作用區(qū)域是該函數(shù),即每次調(diào)用該函數(shù),該變量都會重新回到初始值。
  • 類內(nèi)部的變量。其作用就是該類所產(chǎn)生的對象,即只要該對象沒有被燒毀,則對象內(nèi)部的變量則1直保持。
  • 類內(nèi)部的靜態(tài)變量。其作用是全部進(jìn)程,即只要在該進(jìn)程中,該變量的值就會1直保持,不管使用多少類來構(gòu)造這個(gè)對象,該變量只有1個(gè)賦值,且1直保持。
對類內(nèi)部的靜態(tài)變量而言,不管是從進(jìn)程中那個(gè)線程援用該變量,其值總是相同的,由于編譯器內(nèi)部為靜態(tài)變量分配了單獨(dú)的內(nèi)存空間。但有時(shí)我們卻希望,當(dāng)從同1個(gè)線程中援用該變量時(shí),其值總是相同的, 而從不同的線程援用該變量,其值應(yīng)當(dāng)不同,即我們需要1種作用域?yàn)榫€程的變量定義,這就是線程局部存儲。

ThreadLocal內(nèi)部實(shí)際上是使用弱援用WeakReference來存儲當(dāng)前線程對象,但是不同的線程有不同的ThreadLocal對象,因此會有1個(gè)用于區(qū)分的id,由此內(nèi)部封裝了1個(gè)靜態(tài)內(nèi)部類Values,這個(gè)類就相當(dāng)于1個(gè)map,存儲了每個(gè)線程的實(shí)例的值。

sThreadLocal在prepare()函數(shù)被調(diào)用的時(shí)候就進(jìn)行了1次賦值,即構(gòu)造1個(gè)新的Looper對象存儲到本地線程局部變量中,固然1個(gè)線程只能有1個(gè)Looper對象,否則會拋出以下圖所示的異常。

          

Looper中有2個(gè)用于構(gòu)造Looper對象的方法。1個(gè)是prepare(),另外一個(gè)是prepareMainLooper()。
prepare()我們已說過了,下面說下prepareMainLooper()。
prepareMainLooper(),由方法注釋我們可以知道,這個(gè)利用程序的mainlooper對象是由android環(huán)境創(chuàng)建的,所以你自己永久沒必要調(diào)用這個(gè)函數(shù)。
               

2. Looper

我們可以從類注釋來了解Looper類的作用究竟是干甚么的。

Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare in the thread that is to run the loop, and then loop to have it process messages until the loop is stopped.

Most interaction with a message loop is through the Handler class.

This is a typical example of the implementation of a Looper thread, using the separation of prepare and loop to create an initial Handler to communicate with the Looper.

  class LooperThread extends Thread {
      public Handler mHandler;

      public void run() {
          Looper.prepare();

          mHandler = new Handler() {
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };

          Looper.loop();
      }
  }
Looper類的作用就是給在線程內(nèi)部創(chuàng)建1個(gè)消息循環(huán),固然線程本身內(nèi)部是沒有1個(gè)消息循環(huán)機(jī)制;在run()函數(shù)首行調(diào)用Looper.prepare(),即便創(chuàng)建了1個(gè)消息循環(huán)隊(duì)列,然后在run函數(shù)尾行調(diào)用Looper.loop()則開始處理消息直到消息循環(huán)停止。
大多數(shù)消息循環(huán)的交互是通過Handler類進(jìn)行的。


3. Handler

這里我們只從消息循環(huán)機(jī)制角度來分析這個(gè)Handler。首先看Handler的構(gòu)造函數(shù)
/**
     * Default constructor associates this handler with the queue for the
     * current thread.
     *
     * If there isn't one, this handler won't be able to receive messages.
     */
    public Handler() {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }
         //從TLS(局部線程存儲)中取出已寄存好的Looper對象
        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        //將Looper對象中的MessageQueue賦值給Handler中的對象
        mQueue = mLooper.mQueue;
        mCallback = null;
    }

然后我們在從使用的角度分析,這里我只從異步處理UI界面分析。
我們(程序員)通過 Handler調(diào)用sendMessage()函數(shù)在線程內(nèi)部向UI主線程發(fā)送1個(gè)Message對象,該Message對象會順次通過Handler中的函數(shù)
sendMessage(...) -> sendMessageDelayed(...) -> sendMessageAtTime(...) 
終究會通過sendMessageAtTime發(fā)送消息對象。
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
    {
        boolean sent = false;
        MessageQueue queue = mQueue;
        if (queue != null) {
            msg.target = this;
       
            //將消息對象加入到消息隊(duì)列

            sent = queue.enqueueMessage(msg, uptimeMillis);
        }
        else {
            RuntimeException e = new RuntimeException(
                this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
        }
        return sent;
    }

然后我們在來看看enqueueMessage進(jìn)行了甚么操作。

    final  boolean enqueueMessage(Message msg, long when) {
                      ...

        if (needWake) {
            nativeWake(mPtr);
        }

                      ...
   }

nativeWake是1個(gè)java本地方法,這里觸及了消息機(jī)制中的Sleep-Wakeup機(jī)制,關(guān)于如何喚醒Looper線程的動(dòng)作,這里不做贅述,其終究就是調(diào)用了 native層的Looper的wake函數(shù),喚醒了這個(gè)函數(shù)以后,就開始進(jìn)行消息循環(huán)
 

生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 久久成人在线视频 | 一区二区三区免费在线观看 | 中文字幕精品一区二区三区精品 | 国产一级电影网 | 欧美一级免费看 | 99re视频在线播放 | 亚洲香蕉在线观看 | 成年人在线看片 | 国产黄色一级电影 | 亚洲欧洲无码一区二区三区 | 国产精品日韩欧美一区二区三区 | 51ⅴ精品国产91久久久久久 | 亚洲无线观看 | 欧洲亚洲一区 | 亚洲成人久久久 | 污视频在线观看免费 | 国产精品久久久久久影视 | 亚洲欧美一区二区三区 | 久久这里有精品 | 国产精品久久亚洲 | av看片| 一级久久精品 | 一区二区精品视频 | 日韩一二三区视频 | 成人午夜电影在线观看 | 久久久久久亚洲蜜桃 | 国产精品一区二区三区在线 | 午夜欧美一区二区三区在线播放 | 国产欧美一区二区三区另类精品 | 国产精品一区二区在线看 | 国产精品69久久久久水密桃 | 成人高清在线视频 | 国产福利专区 | 亚洲精品日韩精品 | 精品九九九九九 | 第四色中文综合网 | 日韩免费av| 毛片一区二区三区 | 免费一区二区三区 | 在线视频国产一区 | 免费看成年人视频在线观看 |