詳解Android的兩種事件處理機(jī)制
UI編程通常都會(huì)伴隨事件處理,Android也不例外,它提供了兩種方式的事件處理:基于回調(diào)的事件處理和基于監(jiān)聽器的事件處理。
對(duì)于基于監(jiān)聽器的事件處理而言,主要就是為Android界面組件綁定特定的事件監(jiān)聽器;對(duì)于基于回調(diào)的事件處理而言,主要做法是重寫Android組件特定的回調(diào)函數(shù),Android大部分界面組件都提供了事件響應(yīng)的回調(diào)函數(shù),我們主要重寫它們就行。
一 基于監(jiān)聽器的事件處理
相比于基于回調(diào)的事件處理,這是更具“面向?qū)ο蟆毙再|(zhì)的事件處理方式。在監(jiān)聽器模型中,主要涉及三類對(duì)象:
1)事件源Event Source:產(chǎn)生事件的來源,通常是各種組件,如按鈕,窗口等。
2)事件Event:事件封裝了界面組件上發(fā)生的特定事件的具體信息,如果監(jiān)聽器需要獲取界面組件上所發(fā)生事件的相關(guān)信息,一般通過事件Event對(duì)象來傳遞。
3)事件監(jiān)聽器Event Listener:負(fù)責(zé)監(jiān)聽事件源發(fā)生的事件,并對(duì)不同的事件做相應(yīng)的處理。
基于監(jiān)聽器的事件處理機(jī)制是一種委派式Delegation的事件處理方式,事件源將整個(gè)事件委托給事件監(jiān)聽器,由監(jiān)聽器對(duì)事件進(jìn)行響應(yīng)處理。這種處理方式將事件源和事件監(jiān)聽器分離,有利于提供程序的可維護(hù)性。
舉例:
View類中的OnLongClickListener監(jiān)聽器定義如下:(不需要傳遞事件)
public interface OnLongClickListener {
boolean onLongClick(View v);
}
public interface OnLongClickListener {
boolean onLongClick(View v);
}
View類中的OnLongClickListener監(jiān)聽器定義如下:(需要傳遞事件MotionEvent)
public interface OnTouchListener {
boolean onTouch(View v, MotionEvent event);
}
public interface OnTouchListener {
boolean onTouch(View v, MotionEvent event);
}
二 基于回調(diào)的事件處理
相比基于監(jiān)聽器的事件處理模型,基于回調(diào)的事件處理模型要簡(jiǎn)單些,該模型中,事件源和事件監(jiān)聽器是合一的,也就是說沒有獨(dú)立的事件監(jiān)聽器存在。當(dāng)用戶在GUI組件上觸發(fā)某事件時(shí),由該組件自身特定的函數(shù)負(fù)責(zé)處理該事件。通常通過重寫Override組件類的事件處理函數(shù)實(shí)現(xiàn)事件的處理。
舉例:
View類實(shí)現(xiàn)了KeyEvent.Callback接口中的一系列回調(diào)函數(shù),因此,基于回調(diào)的事件處理機(jī)制通過自定義View來實(shí)現(xiàn),自定義View時(shí)重寫這些事件處理方法即可。
public interface Callback {
// 幾乎所有基于回調(diào)的事件處理函數(shù)都會(huì)返回一個(gè)boolean類型值,該返回值用于
// 標(biāo)識(shí)該處理函數(shù)是否能完全處理該事件
// 返回true,表明該函數(shù)已完全處理該事件,該事件不會(huì)傳播出去
// 返回false,表明該函數(shù)未完全處理該事件,該事件會(huì)傳播出去
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 {
// 幾乎所有基于回調(diào)的事件處理函數(shù)都會(huì)返回一個(gè)boolean類型值,該返回值用于
// 標(biāo)識(shí)該處理函數(shù)是否能完全處理該事件
// 返回true,表明該函數(shù)已完全處理該事件,該事件不會(huì)傳播出去
// 返回false,表明該函數(shù)未完全處理該事件,該事件會(huì)傳播出去
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);
}
三、比對(duì)
基于監(jiān)聽器的事件模型符合單一職責(zé)原則,事件源和事件監(jiān)聽器分開實(shí)現(xiàn);
Android的事件處理機(jī)制保證基于監(jiān)聽器的事件處理會(huì)優(yōu)先于基于回調(diào)的事件處理被觸發(fā);
某些特定情況下,基于回調(diào)的事件處理機(jī)制會(huì)更好的提高程序的內(nèi)聚性。
四、基于自定義監(jiān)聽器的事件處理流程
在實(shí)際項(xiàng)目開發(fā)中,我們經(jīng)常需要自定義監(jiān)聽器來實(shí)現(xiàn)自定義業(yè)務(wù)流程的處理,而且一般都不是基于GUI界面作為事件源的。這里以常見的app自動(dòng)更新為例進(jìn)行說明,在自動(dòng)更新過程中,會(huì)存在兩個(gè)狀態(tài):下載中和下載完成,而我們的程序需要在這兩個(gè)狀態(tài)做不同的事情,“下載中”需要在UI界面上實(shí)時(shí)顯示軟件包下載的進(jìn)度,“下載完成”后,取消進(jìn)度條的顯示。這里進(jìn)行一個(gè)模擬,重點(diǎn)在說明自定義監(jiān)聽器的事件處理流程。
4.1)定義事件監(jiān)聽器如下:
public interface DownloadListener{
public void onDownloading(int porgress);//下載過程中的處理函數(shù)
public void onDownload();//下載完成的處理函數(shù)
}
4.2)實(shí)現(xiàn)下載操作的工具類代碼如下:
public class DownloadUtils{
private static DownloadUtils instance=null;
private private(){
}
public static synchronized DownloadUtils instance(){
if(instance==null){
instance=new DownloadUtils();
}
returns instance;
}
}
private boolean is Downloading=ture;
private int progress=0;
//實(shí)際開發(fā)中這個(gè)函數(shù)需要傳人url作為參數(shù),以獲取服務(wù)器端安裝包位置
public void download(DownloadListener listener)throws interruptdeException{
while (isDownloading){
listener.onDownloading(progress);
//下載過程的簡(jiǎn)單模擬
Thread.sleep(1000);
progress+=10;
if(progress>=100){
isDownloading=false;
}
}
//下載完成
listener.onDownload();
}
}
4.3)最后在main函數(shù)中模擬事件源:
public class DownloadUI{
public static void main(sting[] args){
try{
DownloadUtils.instance().download(new MyDownloadListener());
}catch(InterruptedExceptiob e){
e.printStackTrace();
}
}
private static class MyDownloadListener implements DownloadListener{
@Override
public void onDownloading(int progress){
system.out.println("下載進(jìn)度是:"+progress);
}
@Override
public void onDownloaded(){
system.out.println("下載完成")
}
}
}
運(yùn)行一下的模擬程序,輸入如下所示:

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Flutter組件實(shí)現(xiàn)進(jìn)度指示器
這篇文章主要為大家詳細(xì)介紹了Flutter組件實(shí)現(xiàn)進(jìn)度指示器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-08-08
android開發(fā)教程之listview顯示sqlite數(shù)據(jù)
這篇文章主要介紹了android使用listview顯示sqlite數(shù)據(jù)的方法,需要的朋友可以參考下2014-03-03
Android實(shí)現(xiàn)手機(jī)游戲隱藏虛擬按鍵
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)手機(jī)游戲隱藏虛擬按鍵,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-08-08
Android啟動(dòng)初始化方案App StartUp的應(yīng)用詳解
這篇文章主要介紹了Android啟動(dòng)初始化方案App StartUp的使用方法,StartUp是為了App的啟動(dòng)提供的一套簡(jiǎn)單、高效的初始化方案,下面我們來詳細(xì)了解2022-09-09
使用科大訊飛語音SDK實(shí)現(xiàn)文字在線合成語音
這篇文章主要介紹了使用科大訊飛語音SDK實(shí)現(xiàn)文字在線合成語音 的相關(guān)資料,需要的朋友可以參考下2015-12-12
深入解讀Android的內(nèi)部進(jìn)程通信接口AIDL
這篇文章主要介紹了Android的內(nèi)部進(jìn)程通信接口AIDL,重點(diǎn)講解了進(jìn)程間的通信與AIDL內(nèi)存使用方面的parcelable接口的實(shí)現(xiàn),需要的朋友可以參考下2016-04-04
Android Recyclerview實(shí)現(xiàn)多選,單選,全選,反選,批量刪除的功能
本篇文章主要介紹了Android Recyclerview 實(shí)現(xiàn)多選,單選,全選,反選,批量刪除的功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06

