編輯:關於Android編程
本篇開始分析按鍵消息事件分發(PS:本篇文章中源碼均是android 6.0,請知曉)先看下Agenda:
ViewRootImpl中的dispatchInputEvent方法 View.dispatchKeyEvent方法 ViewGroup.dispatchKeyEvent方法 Activity.dispatchKeyEvent方法 按鍵消息事件時序圖WMS中接受到消息後,會調用ViewRootImpl中的dispatchInputEvent方法,
如下:
ViewRootImpl.java -> dispatchInputEvent()
下面看ViewRootHandler的handleMessage方法:
ViewRootImpl$ViewRootHandler.java -> handleMessage()
以上獲取msg中的event,及receiver後,接著調用enqueueInputEvent方法
ViewRootImpl.java -> enqueueInputEvent()<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPjxpbWcgYWx0PQ=="這裡寫圖片描述" src="/uploadfile/Collfiles/20160829/201608290930451281.png" title="\" />
以上方法,由於默認是false,會執行2:
ViewRootImpl.java -> scheduleProcessInputEvents()
以上方法,再給Handler發一條MSG_PROCESS_INPUT_EVENTS(處理的消息)
ViewRootImpl$ViewRootHandler.java -> handleMessage()
ViewRootImpl.java -> doProcessInputEvents()
上面有個循環操作,就是把QueuedInputEvent傳遞到deliverInputEvent方法中,主要的作用,就是把上面來的按鍵消息放到隊列中去。
ViewRootImpl.java -> deliverInputEvent()
ViewRootImpl提供一個setView方法,是一個public的,會把mView(也就是DecorView),WMS調用這個方法,注意ViewRootImpl並不是一個View,它實際上是一個Handler,它的作用如下:
向DecorView分發收到的用戶發起的event事件,如按鍵,觸屏,軌跡球等事件;(這個是在內部類中實現,下面會說)
與WindowManagerService交互,完成整個Activity的GUI的繪制。
看下setView方法
上面有兩個內部類,ViewPostImeInputStage,
ViewRootImpl.java$ViewPostImeInputStage
在看processKeyEvent之前,先看onProcess方法:
ViewRootImpl$ViewPostImeInputStage.java -> processKeyEvent
ViewRootImpl.java -> handleDispatchWindowAnimationStopped()
上面有些代碼比較長,了解下就行,主要是明白processKeyEvent方法:
KeyEvent是InputEvent的子類,而InputEvent是一個事件的基類。
處理接收的事件及分發事件的過程,那麼問題來了?view或者viewGroup是如何收到按鍵消息派發下來的呢?ViewRootImpl內部類ViewPostImeInputStage中的processKeyEvent()方法中有這麼一段
if (mView.dispatchKeyEvent(event)) {//mView是DecorView(書名),但本質上也是View(乳名)
return FINISH_HANDLED;
}
另外鍵盤消息派發到view或ViewGroup中,在ViewRootImpl另一個內部類ViewPreImeInputStage中的processKeyEvent()方法中也有這麼一段如下:
可以看到從這開始就把按鍵消息派發到了view中去,然後看view中的dispatchKeyEvent():
KeyEvent.java -> dispatch()
再來看下ViewGroup中的dispatchKeyEvent()
上面代碼總結為:ViewGroup是重寫了View的dispatchKeyEvent,如果有子view時,分發按鍵消息到子view中去。沒有,直接由父view分發。
到這就完了麼?沒有,Activity中dispatchKeyEvent,這不是個重寫方法:
以上代碼總結為:先讓actionbar優先處理keyEvent,然後通過window處理,處理不了,到window上的DecorView處理。window和decorview的關系,相當於一個是窗戶,一個是粘在窗戶上的紙。所以,decorview可理解為窗戶上的紙。Activity的dispatchKeyEvent,是用於處理KeyEvent相關,子類可以重寫攔截所以的key event消息在分發到window這一層去的時候,所以我們最好做一些正常的處理流程。
主要過程如下:
1、調用onUserInteraction(),可重載該函數在消息派發前做一些處理
2、回調Activity包含的Window對象的superDispatchKeyEvent,該函數繼而調用mDecor.superDispatchKveyEent,該函數繼而又調用super.dispatchKeyEvent,DecorView的父類是FrameLayout,而FrameLayout未重載dispatchKeyEvent,因此最終調用ViewGroup的dispatchKeyEvent
3、如果DecorView未消耗消息,則調用event的dispatch()函數,這裡的第一個參數receiver是Activity對象
寫到這,有一個疑問?就是一個消息怎麼從window派發到viewRoot中去呢?或者說ViewRoot中的按鍵消息是從哪來的?
ViewRoot中有一個內部類: W,W是一個Binder子類(static class W extends IWindow.Stub ),用於接收global window manager的各種消息, 如按鍵消息, 觸摸消息等。 ViewRoot有一個W類型的成員mWindow,ViewRoot在構造中創建一個W的instance並賦值給mWindow(mWindow = new W(this);)。 ViewRoot是Handler的子類, W會通過Looper把消息傳遞給ViewRoot。
一張圖,總結上面的流程:
Android Toolbar:ToolBar是Android 5.0(API Level 21)之後用來取代ActionBar的ToolBar的優勢:Toolbar本身
首先來看下我們實現的效果和360效果的對比:360手機助手效果演示本庫實現的效果(Icon來自360手機助手,侵刪)xml布局文件注:為了美觀,講每個Button的高度以
手機qq聊天記錄裡有重要的信息要怎麼導出?手機qq聊天記錄保存在哪個文件夾,我們一起來看看吧!手機qq導出聊天記錄方法:一、導出與好友的聊天記錄: 操作方
水波紋效果已經不是什麼稀罕的東西了,用過5.0新控件的小伙伴都知道這個效果,可是如果使用一個TextView或者Button或者其它普通控件的話,你是否知道如何給它設置水