基於監聽的事件模型分工更明確,事件源、事件監聽由兩個類分開,所以具備更好的可維護性。java
Android的事件處理機制保證基於監聽的事件監聽器會被優先出發。android
在事件監聽的處理模型中,主要涉及三類對象:
ide
1.Event Source(事件源):事件發生的場所,一般就是各個組件,例如按鈕,窗口,菜單等。
this
2.Event(事件):事件封裝了界面組件上發生的特定事情(一般就是一次用戶操做)。若是程序須要得到界面組件上所發生事情的相關信息,通常經過Event對象來取得。
spa
3.Event Listener(事件監聽器):負責監聽事件源所發生的事件,並對各類事件作出相應的響應。
orm
Android爲不一樣的界面組件提供了不一樣的監聽器接口:
xml
1.View.OnClickListener:單擊事件的事件監聽器必須實現的接口。
對象
2.View.OnCreateContextMenuListener:建立上下文菜單事件的事件監聽器必須實現的接口。
blog
3.View.onFocusChangeListener:焦點改變事件的事件監聽器必須實現的接口。
接口
4.View.OnKeyListener:按鍵事件的事件監聽器必須實現的接口。
5.View.OnLongClickListener:長按事件的事件監聽器必須實現的接口。
6.View.OnTouchListener:觸摸事件的事件監聽器必須實現的接口。
所謂的事件監聽器,其實就是實現了特定接口的java類的實例。在程序中實現事件監聽器,一般有以下幾種形式。
1.內部類形式:將事件監聽器類定義成當前的內部類。
2.外部類形式:將事件監聽器類定義成一個外部類。
3.Activity自己做爲事件監聽器類:讓Activity自己實現監聽器接口,並實現事件處理方法。
4.匿名內部類形式:使用匿名內部類建立事件監聽器對象。
5.直接綁定標籤:爲UI組件的android:onClick屬性指定事件的監聽方法,開發者須要在Activity中定義該事件監聽方法(該方法必須有一個View類型的形參,該形參表明被單擊的UI組件),當用戶單擊該UI組件時,系統將會激發android:onClick屬性所指定的方法。
1.內部類做爲事件監聽器類
使用內部類做爲事件監聽器類的優點:
①使用內部類能夠在當前類中複用該監聽器類
②由於監聽器類是外部類的內部類,因此能夠自由訪問外部類的全部界面組件。
示例:
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/bn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="內部類作爲事件監聽器類" /> </LinearLayout>
MainActivity.java
package com.example.neibulei; public class MainActivity extends Activity { private Button bn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 獲取activity_main界面中的id爲bn按鈕 bn = (Button) findViewById(R.id.bn); // 爲bn按鈕綁定點擊事件監聽器 bn.setOnClickListener(new MyClickListener()); } // 定義一個單擊事件監聽器 class MyClickListener implements View.OnClickListener { @Override // 實現監聽器類必須實現的方法,該方法將會做爲事件處理器 public void onClick(View v) { // TODO Auto-generated method stub //事件處理器作出的響應 Toast.makeText(MainActivity.this, "內部類作爲事件監聽器類", 1).show(); } } }
2.外部類做爲事件監聽器類
外部類做爲事件監聽器類的劣勢:
①事件監聽器一般屬於特定的GUI界面,定義成外部類不利於提升程序的內聚性。
②外部類形式的事件監聽器不能自由訪問GUI界面的類中的組件,變成不夠簡潔。
外部類做爲事件監聽器類的優點:
若是某個事件監聽器確實須要被多個GUI界面所共享,並且主要是完成某種業務邏輯的實現,則能夠考慮使用外部類的形式來定義事件監聽器類。
示例:
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <EditText android:id="@+id/address" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <EditText android:id="@+id/content" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <Button android:id="@+id/bn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="外部類做爲事件監聽器類(發送短信)" /> </LinearLayout>
MainActivity.java
package com.example.waibulei; public class MainActivity extends Activity { EditText address; // 短信發送給這個號碼 EditText content; // 短信內容 Button bn; // 發送按鈕 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 獲取頁面內中的收件人地址、短信內容 address = (EditText) findViewById(R.id.address); content = (EditText) findViewById(R.id.content); bn = (Button) findViewById(R.id.bn); // 爲bn按鈕綁定長按事件監聽器 bn.setOnLongClickListener(new SendSmsListener(this, address, content)); } }
SendSmsListener.java
package com.example.waibulei; public class SendSmsListener implements OnLongClickListener { private Activity act; private EditText address;// 短信發送給這個號碼 private EditText content;// 短信內容 // 構造方法取得上下文環境,得到兩個文本框控件 public SendSmsListener(Activity act, EditText address, EditText content) { this.act = act; this.address = address; this.content = content; } @Override public boolean onLongClick(View v) { // 取出號碼與短信內容 String addressStr = address.getText().toString().trim(); String contentStr = content.getText().toString().trim(); // 獲取短信管理器 SmsManager smsManager = SmsManager.getDefault(); // 發送文本短信 smsManager.sendTextMessage(addressStr, null, contentStr, null, null); return false; } }
在AndroidManifest.xml上添加發送短信的權限
<uses-permission android:name="android.permission.SEND_SMS" />
3.Activity自己做爲事件監聽器
Activity自己做爲事件監聽器的劣勢:
①這種形式可能形成程序結構混亂,Activity的主要職責應該是完成界面初始化工做,但此時還須要包含事件處理器的方法,從而引發混亂。
②若是Activity界面類須要實現監聽器接口,讓人感受比較怪異。
Activity自己做爲事件監聽器的優點:
直接在Activity類中定義事件處理方法,很是簡潔。
示例:
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/bn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Activity自己做爲事件監聽器" /> </LinearLayout>
MainActivity.java
package com.example.activitybenshen; //實現事件監聽器接口 public class MainActivity extends Activity implements OnClickListener { private Button bn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bn = (Button) findViewById(R.id.bn); // 直接使用Activity做爲監聽器 bn.setOnClickListener(this); } @Override // 實現事件處理方法 public void onClick(View v) { // TODO Auto-generated method stub Toast.makeText(MainActivity.this, "直接使用Activity做爲監聽器", 1).show(); } }
4.匿名內部類做爲事件監聽器類
匿名內部類做爲事件監聽器類的優點:
大部分時候,事件處理器都沒有什麼複用價值(可複用代碼一般都被抽象成了業務邏輯方法),所以大部分事件監聽器只是臨時使用一次,因此使用匿名內部類形式的事件監聽器更合適。
匿名內部類做爲事件監聽器類的劣勢:
語法不宜掌握。
示例:
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:id="@+id/bn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="匿名內部類做爲事件監聽器類" /> </LinearLayout>
MainActivity.java
package com.example.nimingneibulei; public class MainActivity extends Activity { private Button bn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bn = (Button) findViewById(R.id.bn); // 使用匿名內部類做爲事件監聽器 bn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // 事件監聽器的響應 Toast.makeText(MainActivity.this, "匿名內部類做爲事件監聽器", 1).show(); } }); } }
5.直接綁定到標籤
對於不少Android界面組件標籤而言,它們都支持OnClick屬性,該屬性值就是一個形如xxx(View source)的方法的方法名。
示例:
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="clickHandler" android:text="直接綁定到標籤onClick" /> </LinearLayout>
MainActivity.java
package com.example.onclick; public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } // 定義一個事件處理方法 // 其中source參數表明事件源 public void clickHandler(View source) { Toast.makeText(MainActivity.this, "直接綁定到標籤onClick", 1).show(); } }