postDelayed 源碼分析-[Android_YangKe]

1> 內(nèi)部調(diào)用 sendMessageDelayed 函數(shù)

  public final boolean postDelayed(Runnable r, long delayMillis){
     return sendMessageDelayed(getPostMessage(r), delayMillis);
 }

2> sendMessageDelayed 函數(shù)內(nèi)部調(diào)用 sendMessageDelayed

  public final boolean sendMessageDelayed(Message msg, long delayMillis){
     if (delayMillis < 0) {
         delayMillis = 0;
     }
     return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
  }

3> sendMessageDelayed 內(nèi)部調(diào)用 sendMessageAtTime

 public boolean sendMessageAtTime(Message msg, long uptimeMillis{
     MessageQueue queue = mQueue;
     if (queue == null) {
         RuntimeException e = new RuntimeException(this + " sendMessageAtTime() called with no mQueue");
        Log.w("Looper", e.getMessage(), e);
     return false;
    }
  return enqueueMessage(queue, msg, uptimeMillis);
}

4> sendMessageAtTime 內(nèi)部調(diào)用 enqueueMessa

  private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
      msg.target = this;
      if (mAsynchronous) {
          msg.setAsynchronous(true);
      }
    return queue.enqueueMessage(msg, uptimeMillis);
 }

5> enqueueMessage 函數(shù)內(nèi)部調(diào)用queue.enqueueMessage

boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
    throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
    throw new IllegalStateException(msg + " This message is already in use.");
}

synchronized (this) {
    if (mQuitting) {
        IllegalStateException e = new IllegalStateException(
                msg.target + " sending message to a Handler on a dead thread");
        Log.w(TAG, e.getMessage(), e);
        msg.recycle();
        return false;
    }

    msg.markInUse();
    msg.when = when;
    Message p = mMessages;
    boolean needWake;
    if (p == null || when == 0 || when < p.when) {
        // New head, wake up the event queue if blocked.
        msg.next = p;
        mMessages = msg;
        needWake = mBlocked;
    } else {
        // Inserted within the middle of the queue.  Usually we don't have to wake
        // up the event queue unless there is a barrier at the head of the queue
        // and the message is the earliest asynchronous message in the queue.
        needWake = mBlocked && p.target == null && msg.isAsynchronous();
        Message prev;
        for (;;) {
            prev = p;
            p = p.next;
            if (p == null || when < p.when) {
                break;
            }
            if (needWake && p.isAsynchronous()) {
                needWake = false;
            }
        }
        msg.next = p; // invariant: p == prev.next
        prev.next = msg;
    }

    // We can assume mPtr != 0 because mQuitting is false.
    if (needWake) {
        nativeWake(mPtr);
    }
}
return true;
}

核心代碼在 enqueueMessage室囊,通過分析可以得到如下的結(jié)論

  • 消息隊(duì)列是在一個(gè)同步的代碼塊中 synchronized (this) {}
  • 如果發(fā)送的消息為空吭狡、延遲時(shí)間為0等,標(biāo)識(shí)了這條信息就是一條普通消息劣纲,不進(jìn)行特殊處理,體現(xiàn)在:if (p == null || when == 0 || when < p.when) {}
  • 如果發(fā)送的消息含有延遲信息育苟,則使用 nativeWake (native 函數(shù)) 函數(shù)進(jìn)行喚醒

實(shí)踐結(jié)論總結(jié):調(diào)用 Handler.postDelayed 函數(shù)不會(huì)造成主線程阻塞慢逾,請(qǐng)看下面例子歧强,應(yīng)用會(huì)先展示onCreate---1反番、onCreate---3沙热、onCreate---2,且延遲消息的也是一個(gè)有序的消息隊(duì)列(先入先出)

handler.postDelayed(new Runnable() {
  @Override
  public void run() {
      Toast.makeText(MainActivity.this,"onCreate---3", Toast.LENGTH_SHORT).show();
   }
   },2000);

   handler.postDelayed(new Runnable() {
   @Override
   public void run() {
       Toast.makeText(MainActivity.this, "onCreate---2", Toast.LENGTH_SHORT).show();
    }
  }, 2000);

  Toast.makeText(MainActivity.this, "onCreate---1", Toast.LENGTH_SHORT).show();

喜歡的話罢缸、雙擊篙贸、評(píng)論、轉(zhuǎn)發(fā)枫疆,動(dòng)一動(dòng)你的小手讓更多的人知道爵川,關(guān)注帥比~楊!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末息楔,一起剝皮案震驚了整個(gè)濱河市寝贡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌值依,老刑警劉巖圃泡,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異鳞滨,居然都是意外死亡洞焙,警方通過查閱死者的電腦和手機(jī)蟆淀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門拯啦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人熔任,你說我怎么就攤上這事褒链。” “怎么了疑苔?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵甫匹,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我惦费,道長(zhǎng)兵迅,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任薪贫,我火速辦了婚禮恍箭,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瞧省。我一直安慰自己扯夭,他們只是感情好鳍贾,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著交洗,像睡著了一般骑科。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上构拳,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天咆爽,我揣著相機(jī)與錄音,去河邊找鬼置森。 笑死伍掀,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的暇藏。 我是一名探鬼主播蜜笤,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼盐碱!你這毒婦竟也來了把兔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤瓮顽,失蹤者是張志新(化名)和其女友劉穎县好,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體暖混,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡缕贡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拣播。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晾咪。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖贮配,靈堂內(nèi)的尸體忽然破棺而出谍倦,到底是詐尸還是另有隱情,我是刑警寧澤泪勒,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布昼蛀,位于F島的核電站,受9級(jí)特大地震影響圆存,放射性物質(zhì)發(fā)生泄漏叼旋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一沦辙、第九天 我趴在偏房一處隱蔽的房頂上張望夫植。 院中可真熱鬧,春花似錦怕轿、人聲如沸偷崩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)阐斜。三九已至衫冻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間谒出,已是汗流浹背隅俘。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留笤喳,地道東北人为居。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像杀狡,于是被迫代替她去往敵國(guó)和親蒙畴。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容