Android事件處理的兩種模型

來源:互聯網
上載者:User

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

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

一 基於監聽器的事件處理

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

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

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

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

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

舉例:

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

public interface OnLongClickListener {<br /> boolean onLongClick(View v);<br />}

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

public interface OnTouchListener {<br /> boolean onTouch(View v, MotionEvent event);<br />}

二 基於回調的事件處理

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

舉例:

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

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

三 比對

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

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

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

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

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

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

public interface DownloadListener {<br />public void onDownloading(int progress); //下載過程中的處理函數<br />public void onDownloaded();//下載完成的處理函數<br />}

4.2)實現下載操作的工具類代碼如下:

public class DownloadUtils {</p><p>private static DownloadUtils instance = null;</p><p>private DownloadUtils() {<br />}</p><p>public static synchronized DownloadUtils instance() {<br />if (instance == null) {<br />instance = new DownloadUtils();<br />}<br />return instance;<br />}</p><p>private boolean isDownloading = true;</p><p>private int progress = 0;</p><p>// 實際開發中這個函數需要傳入url作為參數,以擷取伺服器端的安裝包位置<br />public void download(DownloadListener listener) throws InterruptedException {<br />while (isDownloading) {<br />listener.onDownloading(progress);<br />// 下載過程的簡單類比<br />Thread.sleep(1000);<br />progress += 10;<br />if (progress >= 100) {<br />isDownloading = false;<br />}<br />}<br />// 下載完成<br />listener.onDownloaded();<br />}</p><p>}

4.3)最後在main函數中類比事件來源:

public class DownloadUI {</p><p>public static void main(String[] args) {<br />try {<br />DownloadUtils.instance().download(new MyDownloadListener());<br />} catch (InterruptedException e) {<br />e.printStackTrace();<br />}<br />}</p><p>private static class MyDownloadListener implements DownloadListener {</p><p>@Override<br />public void onDownloading(int progress) {<br />System.out.println("下載進度是:" + progress);<br />}</p><p>@Override<br />public void onDownloaded() {<br />System.out.println("下載完成");<br />}</p><p>} </p><p>}

運行上面的類比程式,輸出如下所示:

五 參考文獻

1)《瘋狂Android講義》

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.