Android 中主線程也叫 UI 線程,那麼從名字上咱們也知道主線程主要是用來建立、更新 UI 的,而其餘耗時操做,好比網絡訪問,或者文件處理,多媒體處理等都須要在子線程中操做,之因此在子線程中操做是爲了保證 UI 的流暢程度,手機顯示的刷新頻率是 60Hz,也就是一秒鐘刷新 60 次,每16.67 毫秒刷新一次,爲了避免丟幀,那麼主線程處理代碼最好不要超過 16 毫秒。當子線程處理完數據後,爲了防止 UI 處理邏輯的混亂,Android 只容許主線程修改 UI,那麼這時候就須要 Handler來充當子線程和主線程之間的橋樑了。
咱們一般將 Handler 聲明在 Activity 中,而後覆寫 Handler 中的 handleMessage 方法,當子線程調用 handler.sendMessage()方法後 handleMessage 方法就會在主線程中執行。這裏面除了 Handler、Message 外還有隱藏的 Looper 和 MessageQueue 對象。在主線程中 Android 默認已經調用了 Looper.preper()方法,調用該方法的目的是在 Looper 中創 建 MessageQueue 成 員 變 量 並 把 Looper對象綁定到當前線程中。 當調用 Handler 的sendMessage(對象)方法的時候就將 Message 對象添加到了 Looper 建立的 MessageQueue隊列中,同時給 Message 指定了 target 對象,其實這個 target 對象就是 Handler 對象。主線程默
認執行了 Looper.looper () 方法, 該方法從 Looper 的成員變量 MessageQueue 中取出 Message,而後調用 Message 的 target 對象的 handleMessage()方法。這樣就完成了整個消息機制。java
2.1 事件分發中的 onTouch 和 onTouchEvent 有什麼區別,又該如何使用?
這兩個方法都是在 View 的 dispatchTouchEvent 中調用的,onTouch 優先於 onTouchEvent執行。若是在 onTouch 方法中經過返回 true 將事件消費掉,onTouchEvent 將不會再執行。另外須要注意的是,onTouch 可以獲得執行須要兩個前提條件,第一 mOnTouchListener 的值不能爲空,第二當前點擊的控件必須是 enable 的。所以若是你有一個控件是非 enable 的,那麼給它註冊 onTouch 事件將永遠得不到執行。對於這一類控件,若是咱們想要監聽它的 touch 事件,就必須經過在該控件中重寫 onTouchEvent 方法來實現。網絡
2.2 請描述一下 Android 的事件分發機制ide
Android 的事件分發機制主要是 Touch 事件分發,有兩個主角:ViewGroup 和 View。Activity的 Touch 事件事實上是調用它內部的 ViewGroup 的 Touch 事件,能夠直接當成 ViewGroup 處理。View 在 ViewGroup 內, ViewGroup 也能夠在其餘 ViewGroup 內, 這時候把內部的 ViewGroup當成 View 來分析。
先分析 ViewGroup 的處理流程:首先得有個結構模型概念:ViewGroup 和 View 組成了一棵樹形結構,最頂層爲 Activity 的 ViewGroup,下面有若干的 ViewGroup 節點,每一個節點之下又有若干的 ViewGroup 節點或者 View 節點,依次類推。如圖:函數
當一個 Touch 事件(觸摸事件爲例)到達根節點,即 Acitivty 的 ViewGroup 時,它會依次下發,下發的過程是調用子 View(ViewGroup)的 dispatchTouchEvent 方法實現的。簡單來講,就是ViewGroup 遍歷它包含着的子 View,調用每一個 View 的 dispatchTouchEvent 方法,而當子 View爲 ViewGroup 時,又會經過調用 ViwGroup 的 dispatchTouchEvent 方法繼續調用其內部的 View的 dispatchTouchEvent 方法。上述例子中的消息下發順序是這樣的:①-②-⑤-⑥-⑦-③-④。
dispatchTouchEvent 方法只負責事件的分發,它擁有 boolean 類型的返回值,當返回爲 true 時,順序下發會中斷。在上述例子中若是⑤的dispatchTouchEvent 返回結果爲 true,那麼⑥-⑦-③-④將都接收不到本次 Touch 事件。oop
1.Touch 事 件 分 發 中 只 有 兩 個 主 角 :ViewGroup 和 View。ViewGroup 包 含onInterceptTouchEvent 、 dispatchTouchEvent、onTouchEvent 三個相關事件。 View包含dispatchTouchEvent、onTouchEvent 兩個相關事件。其中 ViewGroup 又繼承於 View。post
2.ViewGroup 和 View 組成了一個樹狀結構,根節點爲 Activity 內部包含的一個 ViwGroup。spa
3.觸摸事件由 Action_Down、Action_Move、Aciton_UP 組成,其中一次完整的觸摸事件中,Down 和 Up 都只有一個,Move 有若干個,能夠爲 0 個。線程
4.當 Acitivty 接收到 Touch 事件時,將遍歷子 View 進行 Down 事件的分發。ViewGroup 的遍歷能夠當作是遞歸的。分發的目的是爲了找到真正要處理本次完整觸摸事件的 View,這個 View 會在 onTouchuEvent 結果返回 true。對象
5.當某個子 View 返回 true 時, 會停止 Down 事件的分發, 同時在 ViewGroup 中記錄該子 View。接下去的 Move 和 Up 事件將由該子 View 直接進行處理。 因爲子 View 是保存在 ViewGroup 中的,多層 ViewGroup 的節點結構時,上級 ViewGroup 保存的會是真實處理事件的 View 所在的ViewGroup 對象:如 ViewGroup0-ViewGroup1-TextView 的結構中,TextView 返回了 true,它將被保存在 ViewGroup1 中,而 ViewGroup1 也會返回 true,被保存在ViewGroup0 中。當 Move和 UP 事件來時,會先從 ViewGroup0 傳遞至 ViewGroup1,再由 ViewGroup1 傳遞至 TextView。blog
6.當 ViewGroup 中全部子 View 都不捕獲 Down 事件時,將觸發 ViewGroup 自身的 onTouch事件。觸發的方式是調用 super.dispatchTouchEvent 函數,即父類 View 的 dispatchTouchEvent方法。在全部子 View 都不處理的狀況下,觸發 Acitivity 的 onTouchEvent 方法。
7.onInterceptTouchEvent 有兩個做用:1.攔截 Down 事件的分發。2.停止 Up 和 Move 事件向目標 View 傳遞,使得目標 View 所在的 ViewGroup 捕獲 Up 和 Move 事件。
三、子線程發消息到主線程進行更新 UI,除了 handler 和 AsyncTask,還有什麼?
(1)用 Activity 對象的 runOnUiThread 方法更新在子線程中經過 runOnUiThread()方法更新 UI:
(2)用 View.post(Runnable r)方法更新 UI
四、子線程中能不能 new handler?爲何?
不能,若是在子線程中直接 new Handler()會拋出異常 java.lang.RuntimeException: Can't create handler inside thread that has not called