Android 事件机制 - 监听
Android UI 控件方面就告一段落了,还有一些其它的 UI 控件没讲,但大多都是大同小异,相信你学习了辣么多的,自己去学其它的应该没啥问题
本章节开始我们讲讲 Android 中的事件处理机制
事件处理机制
不管是桌面应用还是手机应用程序,面对最多的就是用户,经常需要处理的就是用户动作,也就是需要为用户动作提供响应,这种为用户动作提供响应的机制就是事件处理
比如,用户点击 没有账号 就要跳转到注册页面,点击 忘记密码 就要跳转到重置密码界面
Android 提供了两套事件处理机制
-
基于监听的事件处理
这种事件处理方式就是给 Android UI 控件绑定特定的事件监听器
-
基于回调的事件处理
这种事件处理方式就是重写 Android UI 控件的特定事件回调方法,或者重写 Activity 特定的回调方法
一般情况下我们推荐使用 基于回调的事件处理 ,但特殊情况下,只能使用 基于监听的事件处理
基于监听的事件处理机制
事件监听机制中由 事件源 , 事件 , 事件监听器 三类对象组成
三者之间的关系和 基于监听的事件处理机制 的一般流程如下图
- 为某个事件源(组件)设置一个监听器,用于监听用户操作
- 用户的操作,触发了事件源的监听器
- 生成了对应的事件对象
- 将这个事件源对象作为参数传给事件监听器
- 事件监听器对事件对象进行判断,执行对应的事件处理器(对应事件的处理方法)
所以,我们也可以说
事件监听机制是一种委派式的事件处理机制,事件源(组件)事件处理委托给事件监听器 当事件源发生指定事件时,就通知指定事件监听器,执行相应的操作
五种不同的使用方式
我们可以使用五种方式给一个 UI 控件或 Activity
添加基于监听的事件
- 直接用匿名内部类 (推荐)
- 使用内部类
- 使用外部类
- 直接使用 Activity 作为事件监听器 (常用)
- 直接绑定到标签
我们以 单击按钮,Toast 提示信息 简单教程,简单编程 为例
-
创建一个 空的 Android 项目
cn.twle.android.EventListen
-
修改
activity_main.xml
添加一个按钮<?xml version="1.0" encoding="utf-8" ?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:orientation="vertical" > <Button android:layout_marginTop="16dp" android:id="@+id/btn_ev" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="提示信息"/> </LinearLayout>
直接用匿名内部类
就是直接使用匿名类调用 setXxxListener()
,重写里面的方法
这是最常用的一种,通常是临时使用一次
修改 MainAcivity.java
package cn.twle.android.eventlisten; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; import android.support.v7.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn_ev = (Button) findViewById(R.id.btn_ev); btn_ev.setOnClickListener(new OnClickListener() { //重写点击事件的处理方法 onClick() @Override public void onClick(View v) { //显示 Toast 信息 Toast.makeText(getApplicationContext(), "简单教程,简单编程", Toast.LENGTH_SHORT).show(); } }); } }
使用内部类
添加一个事件内部类,然后实例化一个对象传递给 setXxxListener()
作为对象
这种方法可以复用该事件类,而且可以直接访问外部类的所有界面组件
修改 MainAcivity.java
package cn.twle.android.eventlisten; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.Toast; import android.support.v7.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn_ev = (Button) findViewById(R.id.btn_ev); //直接 new 一个内部类对象作为参数 btn_ev.setOnClickListener(new BtnClickListener()); } //定义一个内部类,实现 View.OnClickListener 接口,并重写 onClick() 方法 class BtnClickListener implements View.OnClickListener { @Override public void onClick(View v) { Toast.makeText(getApplicationContext(), "简单教程,简单编程", Toast.LENGTH_SHORT).show(); } } }
使用外部类
另外创建一个 Java
文件实现事件类
这种形式用的很少,因为外部类不能直接访问用户界面类中的组件,要通过构造方法将组件传入使用
最直接的影响就是代码不够简洁
在 MainActivity.java
同一目录下新建文件 MsClick.java
package cn.twle.android.eventlisten; import android.content.Context; import android.view.View; import android.view.View.OnClickListener; import android.widget.Toast; public class MsClick implements OnClickListener { private String msg; private Context mContext; //把要提示的文本作为参数传入 public MsClick(Context mContext,String msg) { this.msg = msg; this.mContext = mContext; } @Override public void onClick(View v) { // 提示传入的信息 Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show(); } }
然后修改 MainActivity.java
package cn.twle.android.eventlisten; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; import android.support.v7.app.AppCompatActivity; public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn_ev = (Button) findViewById(R.id.btn_ev); //直接 new 一个外部类,并把 "简单教程,简单编程" 作为参数传入 btn_ev.setOnClickListener(new MsClick(MainActivity.this,"简单教程,简单编程")); } }
直接使用 Activity 作为事件监听器
让 Activity
类实现 XxxListener
事件监听接口,然后在 Activity
中定义重写对应的事件处理器方法,最后调用 setXxx.Listener(this)
比如,Actitity
实现了 OnClickListener
接口,重写 onClick(view)
方法在为某些 UI 控件添加该事件监听对象
修改 MainAcivity.java
package cn.twle.android.eventlisten; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; import android.support.v7.app.AppCompatActivity; //让 Activity 方法实现 OnClickListener 接口 public class MainActivity extends AppCompatActivity implements View.OnClickListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button btn_ev = (Button) findViewById(R.id.btn_ev); //直接写个 this btn_ev.setOnClickListener(this); } //重写接口中的抽象方法 @Override public void onClick(View v) { Toast.makeText(getApplicationContext(), "简单教程,简单编程", Toast.LENGTH_SHORT).show(); } }
直接绑定到标签
就是直接在 xml 布局文件中对应的 Activity 中定义一个事件处理方法
public void msClick(View source)
source 对应事件源( UI 控件类型),接着布局文件中对应要触发事件的 UI 控件设置一个属性
android:onclick = "msClick
范例
-
修改 MainAcivity.java
package cn.twle.android.eventlisten; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; import android.support.v7.app.AppCompatActivity; //让 Activity 方法实现 OnClickListener 接口 public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } //自定义一个方法,传入一个 view 组件作为参数 public void msClick(View source) { Toast.makeText(getApplicationContext(), "简单教程,简单编程", Toast.LENGTH_SHORT).show(); } }
-
修改
activity_main.xml
给Button
添加android:onclick
属性<?xml version="1.0" encoding="utf-8" ?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:orientation="vertical" > <Button android:layout_marginTop="16dp" android:id="@+id/btn_ev" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="msClick" android:text="提示信息"/> </LinearLayout>