當前位置:首頁 » 安卓系統 » android事件的傳遞機制

android事件的傳遞機制

發布時間: 2023-02-18 08:14:11

㈠ android事件分發機制 什麼意思

android事件分發機制 就是一個觸摸事件發生了,從一個窗口傳遞到一個視圖,再傳遞到另外一個視圖,最後被消費的過程,在android中還是比較復雜的傳遞流程如下:

(1) 事件從Activity.dispatchTouchEvent()開始傳遞,只要沒有被停止或攔截,從最上層的View(ViewGroup)開始一直往下(子View)傳遞。子View可以通過onTouchEvent()對事件進行處理。

(2) 事件由父View(ViewGroup)傳遞給子View,ViewGroup可以通過onInterceptTouchEvent()對事件做攔截,停止其往下傳遞。

(3) 如果事件從上往下傳遞過程中一直沒有被停止,且最底層子View沒有消費事件,事件會反嚮往上傳遞,這時父View(ViewGroup)可以進行消費,如果還是沒有被消費的話,最後會到Activity的onTouchEvent()函數。

(4) 如果View沒有對ACTION_DOWN進行消費,之後的其他事件不會傳遞過來。

(5) OnTouchListener優先於onTouchEvent()對事件進行消費。

上面的消費即表示相應函數返回值為true。

㈡ Android 點擊回調傳遞

在使用MultiTypeAdapter實現RecyclerView多類型顯示的時候,會創建一個ViewHolder和ViewBinder,此時如果要在Activity或者Fragment相應點擊事件的時候,需要在ViewHolder和ViewBinder之間做傳遞。如果一個ViewHolder下有RecyclerView,然後也使用了MultiTypeAdapter,那麼這個點擊事件的回調將會是一件相當頭疼的事情。

在使用 LifeCycle 時,發現他只需要當前類實現 LifecycleObserver ,然後通過調用 addObserver 方法即可實現事件傳遞。由此想到點擊事件是否也可以使用此種形式來實現。

DEMO

在受到 LifeCycle 的啟發下,模仿這寫了幾個類。

一個點擊事件如果在某個類中如果需要做操作,那麼需要實現該介面。

繼承OnItemClick,並實現具體的方法。

基本點擊事件Observer

這一層,對事件在OnBindViewHolder中做了一次傳遞,通過dispatchObserver方法,將ViewBinder中的事件傳遞到了ViewHolder中。

定義兩個點擊事件。

創建實體類,和Binder相對應。

在覆寫 setData 方法的時候,一定要調用super。不然事件無法傳遞。

響應事件的回調,只需要調用 getObserver 方法,然後傳入對應的Observer,如果有,就直接調用方法。

adapter傳遞事件,也是通過dispatchObserver方法。

ViewBinder其實就不需要做什麼事情了,比較簡單。

㈢ Android-從重疊view響應問題到安卓事件分發機制

工作當中遇到一個需求:有兩個重疊並且全屏的Framelayout,交互邏輯是點擊上層的button使得上層消失,下層可見;再點擊下層使得下層消失上層出現。但是發現當點擊上層非button區域時,下層也會響應點擊事件,但是點擊button區域則不會。這意味著點擊事件穿過上層到達下層。對於安卓事件機制一知半解的我無從下手,上網搜了一下發現在上層FrameLayout下增加:

這樣的確可以保證上層點擊事件不會到達下層,可是這是為什麼呢?最初步的猜想是當上層FrameLayout的clickable屬性為true時,點擊事件已經被上層攔截了。這個和當你點擊button時響應onclick()時的原理是不是一樣?這就需要從源碼分析了。

分析源碼前先大致了解一下安卓事件分發機制。

綜合上述對安卓事件分發的源碼分析知道,當在上層FrameLayout中將clickable設置為true時,其實就是
當點擊事件到達上層framelayout時,在onTouchEvent中對事件進行攔截,使得點擊事件不會繼續向下傳遞。當然,除了這個方法以外,也可以重寫FrameLayout的onInterceptTouchEvent,在將這個函數的返回值為true,也可以實現攔截事件的作用。

㈣ Framework事件機制——手撕Android事件處理的三種方法

Android的事件處理的三種方法:

setOnClickListener,setOnLongClickListener、setOnTouchListener

注意:如果onTouchEvent方法return true,則單擊事件和長摁事件不再執行;若onLongClick方法返回true,則單擊事件不再處理。

需要定義繼承組件的類,重寫回調方法Touch方法執行時,先被Activity捕獲,DispatchTouchEvent方法處理。return false,交給上層的onTouchEvent方法處理;return super.dispatchTouchEvent(ev),則傳遞給最外層的View。

View用Dispatch方法處理,return false,由上層的onTouchEvent方法處理。如果返回super.dispatchTouchEvent(ev),則本層的onInterceptTouchEvent攔截,如果攔截true,則攔截,false不攔截,傳遞給子View的DispatchTouchEvent處理。

常用的回調方法:onKeyDown,onKeyLongPress,onKeyUp,onTouchEvent,onTrackballEvent(軌跡球事件)監聽和回調同時存在時,先調用監聽。

流程模型圖:

Event source 事件源
Event 事件
Event Listener 事件監聽器
下面我們來看一下點擊事件和觸摸事件的監聽三要素具體是那部分:

由於點擊事件比較簡單,系統已經幫我們處理了,並沒有找到具體事件是哪個。

View.OnClickListener 單擊事件監聽器必須實現的接⼝
View.OnCreateContextMenuListener 創建上下⽂菜單事件
View.OnFocusChangeListener 焦點改變事件
View.OnKeyListener 按鍵事件監聽器
View.OnLongClickListener 長按事件監聽器
View.OnTouchListener 觸摸屏事件監聽器

⾸先,事件監聽機制中由事件源,事件,事件監聽器三類對象組成。
事件監聽器處理流程:

在此以OnClickListener單擊事件為例使用intent來實現頁面的跳轉

監聽事件處理是事件源與事件監聽器分開的而基於回調的事件處理UI組件不但是事件源,而且還是事件監聽器,通過組件的相關回調方法處理對應的事件。

Ⅰ. 自定義View類,繼承自需要的View UI類。ex :自定義 MyButton按鈕類 extends 基礎Button類

Ⅱ. 復寫回調函數。ex:public boolean onTouchEvent(MotionEvent event)

每一個事件回調方法都會返回一個boolean值,①.如果返回true:表示該事件已被處理,不再繼續向外擴散,②.如果返回false:表示事件繼續向外擴散

而說到基於回調就離不開監聽機制

幾乎所有基於回調的事件處理方法都有一個boolean類型的返回值,該返回值用於表示該處理方法是否能完全處理該事件。
如果處理事件的回調方法返回true,表明該處理方法已經完全處理改事件,該事件不會傳播出去。
如果處理事件的回調方法返回false,表明該處理方法並未完全處理該事件,該事件會傳播出去。
對於基於回調的時間傳播而言,某組件上所發生的事件不僅會激發該組件上的回調方法,也會觸發該組件所在Activity的回調方法——只要事件能傳播到該Activity。

這里是在模擬器里進行的測試,這里按下鍵盤(而不是點擊),會看到 logcat 中的輸出,如下:

View類實現了KeyEvent.Callback介面中的一系列回調函數,因此,基於回調的事件處理機制通過自定義View來實現,自定義View時重寫這些事件處理方法即可。

Handler是一個消息分發對象。

Handler是Android系統提供的一套用來更新UI的機制,也是一套消息處理機制,可以通過Handler發消息,也可以通過Handler處理消息。

在下面介紹Handler機制前,首先得了解以下幾個概念:

在子線程執行完耗時操作,當Handler發送消息時,將會調用 MessageQueue.enqueueMessage ,向消息隊列中添加消息。 當通過 Looper.loop 開啟循環後,會不斷地從消息池中讀取消息,即調用 MessageQueue.next , 然後調用目標Handler(即發送該消息的Handler)的 dispatchMessage 方法傳遞消息, 然後返回到Handler所在線程,目標Handler收到消息,調用 handleMessage 方法,接收消息,處理消息。

從上面可以看出,在子線程中創建Handler之前,要調用 Looper.prepare() 方法,Handler創建後,還要調用 Looper.loop() 方法。而前面我們在主線程創建Handler卻不要這兩個步驟,因為系統幫我們做了。

初始化Looper

從上可以看出,不能重復創建Looper,每個線程只能創建一個。創建Looper,並保存在 ThreadLocal 。其中ThreadLocal是線程本地存儲區(Thread Local Storage,簡稱TLS),每個線程都有自己的私有的本地存儲區域,不同線程之間彼此不能訪問對方的TLS區域。

開啟Looper

發送消息

post方法:

send方法:

在子線程中,進行耗時操作,執行完操作後,發送消息,通知主線程更新UI。

本文講解了三個方面;Android事件機制;基於監聽、基於回調以及Handler消息處理。還有許多沒有講解到的知識點,我總結在了整理的一套Android進階筆記裡面;需要學習進階的同學可以前往獲取: Frame Work源碼解析手冊 、 Android核心技術進階手冊、實戰筆記、面試題綱資料

㈤ 請簡述什麼是android事件處理,並分析兩種android事件處理機制的實現過程和區別

UI編程通常都會伴隨事件處理,Android也不例外,它提供了兩種方式的事件處理:基於回調的事件處理和基於監聽器的事件處理。

對於基於監聽器的事件處理而言,主要就是為Android界面組件綁定特定的事件監聽器;對於基於回調的事件處理而言,主要做法是重寫Android組件特定的回調函數,Android大部分界面組件都提供了事件響應的回調函數,我們主要重寫它們就行。


一 基於監聽器的事件處理

相比於基於回調的事件處理,這是更具「面向對象」性質的事件處理方式。在監聽器模型中,主要涉及三類對象:

1)事件源Event Source:產生事件的來源,通常是各種組件,如按鈕,窗口等。

2)事件Event:事件封裝了界面組件上發生的特定事件的具體信息,如果監聽器需要獲取界面組件上所發生事件的相關信息,一般通過事件Event對象來傳遞。

3)事件監聽器Event Listener:負責監聽事件源發生的事件,並對不同的事件做相應的處理。


基於監聽器的事件處理機制是一種委派式Delegation的事件處理方式,事件源將整個事件委託給事件監聽器,由監聽器對事件進行響應處理。這種處理方式將事件源和事件監聽器分離,有利於提供程序的可維護性。

舉例:

View類中的OnLongClickListener監聽器定義如下:(不需要傳遞事件)


[java] view plainprint?

public interface OnLongClickListener {

boolean onLongClick(View v);

}

public interface OnLongClickListener {
boolean onLongClick(View v);
}


View類中的OnLongClickListener監聽器定義如下:(需要傳遞事件MotionEvent)

[java] view plainprint?

public interface OnTouchListener {

boolean onTouch(View v, MotionEvent event);

}

public interface OnTouchListener {
boolean onTouch(View v, MotionEvent event);
}

二 基於回調的事件處理

相比基於監聽器的事件處理模型,基於回調的事件處理模型要簡單些,該模型中,事件源和事件監聽器是合一的,也就是說沒有獨立的事件監聽器存在。當用戶在GUI組件上觸發某事件時,由該組件自身特定的函數負責處理該事件。通常通過重寫Override組件類的事件處理函數實現事件的處理。

舉例:

View類實現了KeyEvent.Callback介面中的一系列回調函數,因此,基於回調的事件處理機制通過自定義View來實現,自定義View時重寫這些事件處理方法即可。

[java] view plainprint?

public interface Callback {

// 幾乎所有基於回調的事件處理函數都會返回一個boolean類型值,該返回值用於

// 標識該處理函數是否能完全處理該事件

// 返回true,表明該函數已完全處理該事件,該事件不會傳播出去

// 返回false,表明該函數未完全處理該事件,該事件會傳播出去

boolean onKeyDown(int keyCode, KeyEvent event);

boolean onKeyLongPress(int keyCode, KeyEvent event);

boolean onKeyUp(int keyCode, KeyEvent event);

boolean onKeyMultiple(int keyCode, int count, KeyEvent event);

}

public interface Callback {
// 幾乎所有基於回調的事件處理函數都會返回一個boolean類型值,該返回值用於
// 標識該處理函數是否能完全處理該事件
// 返回true,表明該函數已完全處理該事件,該事件不會傳播出去
// 返回false,表明該函數未完全處理該事件,該事件會傳播出去
boolean onKeyDown(int keyCode, KeyEvent event);
boolean onKeyLongPress(int keyCode, KeyEvent event);
boolean onKeyUp(int keyCode, KeyEvent event);
boolean onKeyMultiple(int keyCode, int count, KeyEvent event);
}

三 比對

基於監聽器的事件模型符合單一職責原則,事件源和事件監聽器分開實現;

Android的事件處理機制保證基於監聽器的事件處理會優先於基於回調的事件處理被觸發;

某些特定情況下,基於回調的事件處理機制會更好的提高程序的內聚性。


四 基於自定義監聽器的事件處理流程

在實際項目開發中,我們經常需要自定義監聽器來實現自定義業務流程的處理,而且一般都不是基於GUI界面作為事件源的。這里以常見的app自動更新為例進行說明,在自動更新過程中,會存在兩個狀態:下載中和下載完成,而我們的程序需要在這兩個狀態做不同的事情,「下載中」需要在UI界面上實時顯示軟體包下載的進度,「下載完成」後,取消進度條的顯示。這里進行一個模擬,重點在說明自定義監聽器的事件處理流程。

4.1)定義事件監聽器如下:

㈥ Android-View的事件分發及攔截-父控制項和子控制項都處理觸摸事件的方式

比如接著上篇 Android-View的事件分發及攔截機制簡單流程先體驗再研究(場景?疑問? 具體?待續...) ,小白現在要實現就是子View和父ViewGroup都響應點擊事件。

1. 單純的都只是響應down事件

這個就很簡單了 - 直接子View的**public boolean **onTouchEvent(MotionEvent event) 裡面直接返回false就行了。也就是子控制項響應了一次down後,接下來就交給父ViewGroup了.(子View就啥幾把也幹不了了);

2. 響應down和up事件,move啥的

我們知道子View如果onTouch裡面返回了true,那麼將會處理後續的move,up事件。而不再交給上層父ViewGroup。那父ViewGroup就沒辦法在Touch裡面處理,所以我們只能放到dispatchTouchEvent或者onInterceptTouchEvent中處理這個down,up等事件:

比如dispatchTouchEvent中:

這樣的情況就是父ViewGroup先執行點擊事件,然後子View再執行。 如果您需要父ViewGroup晚點,可以延時執行啥的。

如果此時,子View的dispatchTouchEvent返回true - 表示攔截,不繼續了

那麼子View的所有的事件都不會響應了。其實也就是我們的一個事件先傳遞,touch再處理的樹形圖:

網路上拔個圖來

簡單記錄下下而已,繼續加深理解...這是上一篇的續,還是上一篇....嘖嘖....後面是官方文檔分析來著...

㈦ android的事件處理機制有兩種

1.基於監聽的事件處理機制,有一個關鍵就是事件注冊。 但是我們在實踐的時候並沒有自己手動的為某個視圖控制項注冊監聽器。
解答: 我們會經常用到 諸如 setOnclickListener(),OnTouchListener()方法等。 從字面意義理解,它為設置...監聽器。 但是,它 跟注冊還是頗有一些區別的。 我想注冊實踐監聽器,就是將它掛在在一個線程上,也就是說有一個事件監聽線程,那麼,有事件的視圖,就至少是雙線程的程序了。 不過很可惜,在去看set..Listener的源碼的時候,是看不到它在java源碼方面的具體實現的。 也就是說,要麼它依賴操作系統實現,要麼它依賴jni實現,並且,事件線程由jni管理。 換言之,實現注冊監聽是由ni實現的。
2.事件源的觸發流程:
解答: 學習過操作系統朋友應該知道,操作系統的很多操作都是通過中斷來完成。 同理,比如一個點擊事件,android手機硬體中,包括了一個觸摸屏的硬體,它分為內屏和外屏。 其中負責觸發屏幕點擊和觸摸中斷的為內屏。 內屏大概由五個層次構成,具體有什麼用不知道,反正我拆過~~~ 從內屏上,當有電容屏感應的時候,會接收到你觸摸的位置信息,甚至觸摸力度!!! 這個消息經由系統中斷(具有最高優先順序,應該是由最高優先順序的進程通知)發送給cpu,經由cpu通過進程間的消息機制傳遞給這個進程(當前正在用戶界面運行的進程,這時候只有一個),也就是這個程序運行的內存空間的某個點。(或者說通過廣播機制,將這個事件發送給所有的app也是有可能的)。

㈧ Android事件分發機制

Android中對視圖的Touch事件進行分發處理。
單手指操作:ACTION_DOWN -> ACTION_MOVE -> ACTION_UP
多手指操作:ACTION_DOWN -> ACTION_POINTER_DOWN -> ACTION_MOVE -> ACTION_POINTER_UP -> ACTION_UP.

(1) dispatchTouchEvent() :事件分發

(2) onInterceptTouchEvent() :事件攔截

(3) onTouchEvent() :事件處理

ViewGroup 的相關事件有三個:onInterceptTouchEvent、dispatchTouchEvent、onTouchEvent。

View 的相關事件只有兩個:dispatchTouchEvent、onTouchEvent。

先分析ViewGroup的處理流程:首先得有個結構模型概念:ViewGroup和View組成了一棵樹形結構,最頂層為Activity的ViewGroup,下面有若乾的ViewGroup節點,每個節點之下又有若乾的ViewGroup節點或者View節點,依次類推。如圖:

點擊事件達到頂級 View(一般是一個 ViewGroup),會調用 ViewGroup 的 dispatchTouchEvent 方法,如果頂級 ViewGroup 攔截事件即 onInterceptTouchEvent 返回 true,則事件由 ViewGroup 處理,這時如果 ViewGroup 的 mOnTouchListener 被設置,則 onTouch 會被調用,否則 onTouchEvent 會被調用。也就是說如果都提供的話,onTouch 會屏蔽掉 onTouchEvent。在 onTouchEvent 中,如果設置了 mOnClickListenser,則 onClick 會被調用。如果頂級 ViewGroup 不攔截事件,則事件會傳遞給它所在的點擊事件鏈上的子 View,這時子 View 的 dispatchTouchEvent 會被調用。如此循環。

㈨ Android OkHttp3 :最簡單&粗暴(使用與原理)講解

注釋1:WebSocket是一個介面,它的實現類RealWebSocket,該類完成WebSocket的連接、數據請求與接收功能。

注釋1:將RealCall實例添加至Dispatcher中(下文會介紹Dispatcher)。
注釋2:通過()獲取響應。
注釋3:通過封裝好的攔截器集合,獲取第一個攔截器的任務。
注釋4:觸發第一個攔截器的任務,該任務就觸發一下攔截器的任務,以此類推,原理(Android事件傳遞機制)如下圖:

注釋1:把AsyncCall請求對象傳遞進Dispatcher線程池管理;

注釋2:通過()獲取響應;

注釋1:獲取自定義線程池;
注釋2:判斷正在執行的非同步請求數量與請求集合中相同host的數量是否滿足,如果滿足就添加到執行中的集合中,並添加至線程池中執行請求;如果不滿足就添加至待執行請求的集合中,等待執行中的請求完成之後,再執行相同host數量判斷滿足才添加至線程池中執行請求;
注釋3:將請求對象AsyncCall添加進請求執行的集合中;
注釋4:將請求對象AsyncCall添加進線程池中執行;
注釋5:當不滿足執行條件時(注釋2),把請求對象添加至待執行的集合中;
注釋6:每當一個請求執行完畢時,就會調用finished()去掉對應集合中的存儲對象,並在次判斷待執行的集合中是否有滿足條件的請求,若滿足就添加至執行的集合與線程池中執行,若不滿足繼續等待下一個請求完成再次判斷。
注釋7:判斷待執行的集合中是否滿足可執行的對象。

2.RealConnection與HttpCodec初始化(RealConnection在ConnectInterceptor中通過StreamAllocation的newStream()初始化,而HttpCodec在RealConnection中被初始化)

㈩ Android事件分發與回傳機制

[圖片上傳失敗...(image-85aaf7-1630895208631)]

[圖片上傳失敗...(image-8c09b-1630895208631)]

[圖片上傳失敗...(image-25abb8-1630895208631)]

日常處理的部分為RootView下面的ViewGroup和View部分,那麼上面的PhoneWindow、DecorView和RootView是做什麼用的呢?RootView本身可以作為上下溝通的橋梁使用。

(設計模式-組合模式)

PhoneWindow是Window的實現類,Window是抽象類,DecorView是它的一個內部類。所以,PhoneWindow的大部分消息,都是PhoneWindow通過DecorView傳遞給下面的View的,同時下面的View傳遞消息也是通過DecorView回傳給PhoneWindow。

事件的傳遞過程中,主要有三種情況:事件分發(dispatchTouchEvent)、事件攔截(onInterceptTouchEvent)、事件消費(onTouchEvent)。這三種情況均有一個boolean型的返回值來控制事件的傳遞流程。

為什麼只有ViewGroup有事件攔截:因為Activity作為事件分發的開始,攔截了就只能自己處理了;而View作為事件分發的最末端,攔不攔截都需要它處理。中間階段,攔截可做一些處理。

事件傳遞的順序:

Activity -> PhoneWindow -> DecorView -> ViewGroup -> View -> Activity

如果我們點擊View1,系統如何傳遞給View1呢,而不是下面的ViewGroupA或者RootView。很明顯,我們需要一種機制來執行消息的分發。而消息分發的最小單位是View,ViewGroup是View的子類,Activity是根布局.

事件消費與否與具體消費無關,僅由返回值決定,true表示消費,false表示不消費。

熱點內容
蘋果和安卓哪個看小說方便 發布:2025-07-13 00:20:25 瀏覽:755
網址訪問量查詢 發布:2025-07-13 00:13:25 瀏覽:976
thinkphp關掉緩存 發布:2025-07-12 23:44:01 瀏覽:86
互動平台源碼 發布:2025-07-12 23:42:15 瀏覽:9
矩形密碼是什麼 發布:2025-07-12 23:41:15 瀏覽:407
kvm存儲技術包括 發布:2025-07-12 23:41:15 瀏覽:950
安卓手機網路怎麼設置才好 發布:2025-07-12 23:33:01 瀏覽:272
怎麼修改手機號服務密碼 發布:2025-07-12 23:29:37 瀏覽:158
myeclipsejsp資料庫連接 發布:2025-07-12 23:26:25 瀏覽:553
凱迪拉克ct6電磁懸掛是哪個配置 發布:2025-07-12 23:24:38 瀏覽:597