Android主線程消息循環簡介

主線程消息循環簡介

主線程就是ActivityThread,在ActivityThread的main方法中,新建了Looper並開啓了Looper循環。循環開啓後,每當有新消息進入,Looper會處理對應的消息,處理完後進入休眠狀態,主線程的一系列操作都是在這種循環中完成的,這就是主線程的消息循環。

Handler運行機制

  • 什麼是Handler

    Handler在日常開發中,我們經常會接觸到,通常會用來在非UI線程中調用,用來通知主線程進行一些UI操作。這其實只是Handler的一個使用場景。

    其實Handler是Android消息機制的上層接口,使用Handler可以方便的將一個任務切換到Handler所在的線程中去執行,所以Handler並不是專用來更新UI的,更新UI只是Handler的一個使用場景。

  • Handler、MessageQueue和Looper是如何配合運行的

    Android的消息機制主要是指Handler的運行機制以及Handler所附帶的MessageQueue和Looper的工作過程,這三者實際上是一個整體,只不過我們在開發過程中,比較多的接觸到Handler而已。

    這裏說一下Handler的工作原理:

    • Handler創建時候,會採用當前線程的Looper來構建內部的消息循環系統,如果當前線程沒有Looper則會拋出異常。所以Handler需要在有Looper的線程中運行。
    • 如果當前線程沒有Looper,我們需要創建。創建Looper的方法包括aaabbb,其中第二個方法是主線程專用的創建Looper方法
    • Looper創建完成後,就可以開始消息循環了。每當有新的消息時候,會調用Handler的post方法,實際上post最後調用Handler的send方法,該方法會向MessageQueue中加入一條數據。
    • Looper會不斷的輪詢MessageQueue中的next()方法,當上一步中有數據加入後,next方法會返回新加入的數據,Looper獲取到數據後,回調Handler的disPathMessage方法。
    • 因爲Handler會在Looper所在的線程中運行,所以至此實現了切換一個任務到Handler所在線程執行的操作。

主線程循環爲什麼不會卡死

  • 首先說一下爲什麼Android要採用消息循環的機制來設計UI線程。

    因爲在系統運行中,最小單位是線程,當一個線程運行結束後,系統會銷燬對應線程。而UI線程需要一直運行,爲了保持線程的活力,所以採用死循環的方式來啓動UI線程

  • 死循環是否過於消耗CPU資源?

    主線程的死循環是基於消息隊列機制,當MessageQueue沒有消息時候,主線程都處於休眠狀態,直到下一個消息到達。在休眠裝態時候,並不消耗CPU資源。所以只要不在主線程上進行大量的耗時操作,是不用擔心主線程一直佔用CPU而使應用卡死的。

普通點擊事件中的消息邏輯

  • 事件分發之前的操作

    • 在點擊事件分發之前,其實屏幕的物理點擊操作是通過Handler消息機制來傳遞給主線程的

    • 每個Activity都實現了一個特殊的接口Window.Callback

    • 在Activity的attach方法中,會通過setCallback方法,使window持有Activity對象

    • 在Activity啓動以後,在它的onResume以後,DecorView纔開始attahc給WindowManager,從而顯示出來。在這個過程中會創建ViewRootImpl,在ViewRootImpl的setView中,會通過跨進程的方式向WMS發起一個調用,從而將DecorView最終添加到Window上,在這個過程中,ViewRootImpl、DecorView和WMS會彼此關聯,同時會創建InputChannel、InputQueue和WindowInputEventReceiver來接收點擊事件的消息。

    • 點擊時候,首先會調用ViewRootImpl.dispatchInputEvent()方法,此方法實現效果如下:

      public void dispatchInputEvent(InputEvent event, InputEventReceiver receiver) {
              SomeArgs args = SomeArgs.obtain();
              args.arg1 = event;
              args.arg2 = receiver;
              Message msg = mHandler.obtainMessage(MSG_DISPATCH_INPUT_EVENT, args);
              msg.setAsynchronous(true);
              mHandler.sendMessage(msg);
          }
      
    • 此處可以看出,通過mHandler發出一個消息,這個消息會通過一系列循環的調用,調到DecorView的dispatchTouchEvent方法,這個方法會獲取callback對象,而Activity實現了Callback接口,至此消息傳遞到Activity

    • 具體的Event傳遞過程可以參考大神任玉剛的博客

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章