无论是桌面应用还是手机应用程序,面对用户的使用,经常需要处理的便是用户的各种动作,也就是需要为用户动作提供响应,这种为用户动作提供响应的机制就是事件处理。

Android为我们提供了两套强大的响应机制:基于监听的事件处理和基于回调的事件处理。本文这次讨论的便是基于监听的事件处理。

对于Android基于监听的事件处理而言,主要做法就是为Android界面组件绑定特定的事件监听器,除此之外Android还允许在界面文件为UI组件的android:onClick属性指定事件监听方法,通过这种方式指定监听方法时,开发者需要在activity中定义该事件监听方法,当用户单击该UI组件时,系统将会激发android:onClick属性所指定的方法。

监听的处理模型

基于监听的事件处理是一种更“面向对象”的事件处理,这种处理方式与JavaAWTSwing的处理方式几乎完全相同。

在事件的处理模型中,主要涉及以下三类对象:

  •  Event Source(事件源):事件发生的场所,通常就是各个组件,例如按钮、窗口、菜单等
  •  Event(事件):事件封装了界面组件上发生的特定事情(通常就是一次用户操作)。如果程序需要获得界面组件上所发生事件的相关信息。一般通过Event来取得。
  •  Event Listener(事件监听器):负责监听事件源所发生的事件,并对各种事件做出相应的响应。而这些响应动作实际上就是一系列程序语句,通常以方法的形式组织起来,作为事件监听器的核心——这些方法也被称为事件处理器(Event Handler);

 

当用户按下一个按钮或者一个菜单项时,这些动作便会激发一个相应的事件,该事件就会触发事件源上注册的事件监听器,事件监听器调用对应的事件处理器来做出相应的相应。

 

基于监听的事件处理机制是一种委派式(Delegation)事件处理方式:普通组件(事件源)将整个事件处理委托给特定对象(事件监听器);当该事件源发生指定事件时,就通知所委派的事件监听器,由事件监听器来处理整个事件。

 

基于监听的事件处理模型涉及三个成员:事件源、事件和事件监听器,其中事件源最容易创建,任意界面组件都可以作为事件源;事件的产生无需程序员关心,它是由系统自动产生的;所以实现事件监听器是整个事件处理的核心。

 

内部类作为事件监听器类

使用内部类可以在当前类中复用该监听器类;因为监听器类是外部类的内部类,所以可以自由访问外部类的所有界面组件。这也是内部类作为监听器的优势。下面是一个简单的内部类处理模型,先看布局代码,该布局中只定义了两个组件一个文本框和一个按钮。

 1 <TextView   2         android:id="@+id/txt"   3         android:layout_width="wrap_content"   4         android:layout_height="wrap_content"   5         android:padding="12dp"   6         android:textSize="18sp"/>   7 <Button   8         android:id="@+id/bn"   9         android:text="单击我"  10         android:layout_width="wrap_content"  11         android:layout_height="wrap_content"/>  

下面是程序的Activity:

 

 1 public class MainActivity extends Activity   2 {   3     @Override   4     protected void onCreate(Bundle savedInstanceState)   5     {   6         super.onCreate(savedInstanceState);   7         setContentView(R.layout.activity_main);   8         // 获取应用程序中的bn按钮   9         Button bn = findViewById(R.id.bn);  10         // 为按钮绑定事件监听器  11         bn.setOnClickListener(new MyClickListener()); // ①  12     }  13     // 定义一个单击事件的监听器  14     class MyClickListener implements View.OnClickListener  15     {  16         // 实现监听器类必须实现的方法,该方法将会作为事件处理器  17         @Override  18         public void onClick(View v)  19         {  20             TextView txt = findViewById(R.id.txt);  21             txt.setText("bn按钮被单击了!");  22         }  23     }  24 }  

 

外部类作为事件监听器类

使用外部类定义事件监听器类的形式比较少见,主要因为如下两个原因:

  • 事件监听器通常属于特定的GUI界面,定义成外部类不利于提高程序的内聚性。
  • 外部类形式的事件监听器不能自由访问创建GUI界面的类的组件,编程不够简洁。

如果某个事件监听器确实需要被多个GUI界面所共享,而且主要是完成某种业务逻辑的实现,则可以考虑使用外部类的形式来定义事件监听器类。

下面的程序定义了一个外部类作为OnlongClickListener类,该事件监听器实现了发送短信的功能。界面文件主要由三个组件构成:两个编辑框和一个button

 

 1 <EditText   2     android:id="@+id/address"   3     android:layout_width="match_parent"   4     android:layout_height="wrap_content"   5     android:hint="请填写收信号码"   6     android:inputType="phone" />   7 <EditText   8     android:id="@+id/content"   9     android:layout_width="match_parent"  10     android:layout_height="wrap_content"  11     android:hint="请填写短信内容"  12     android:lines="3" />  13 <Button  14     android:id="@+id/send"  15     android:layout_width="wrap_content"  16     android:layout_height="wrap_content"  17     android:hint="发送" />  

 

SendSmsListener.java

 1 public class SendSmsListener implements View.OnLongClickListener   2 {   3     private Activity act;   4     private String address;   5     private String content;   6    7     public SendSmsListener(Activity act, String address, String content)   8     {   9         this.act = act;  10         this.address = address;  11         this.content = content;  12     }  13     @Override  14     public boolean onLongClick(View source)  15     {  16         // 获取短信管理器  17         SmsManager smsManager = SmsManager.getDefault();  18         // 创建发送短信的PendingIntent  19         PendingIntent sentIntent = PendingIntent.getBroadcast(act,  20                 0, new Intent(), 0);  21         // 发送文本短信  22         smsManager.sendTextMessage(address, null,  23                 content, sentIntent, null);  24         Toast.makeText(act, "短信发送完成", Toast.LENGTH_LONG).show();  25         return false;  26     }  27

上面的事件监听器类没有与任何GUI界面耦合,创建该监听器对象时需要传入两个String对象和一个Activity对象,其中第一个String对象用于作为收信人号码,第二个String用于作为短信内容。

 

 1 public class MainActivity extends Activity   2 {   3     private EditText address;   4     private EditText content;   5    6     @Override   7     protected void onCreate(Bundle savedInstanceState)   8     {   9         super.onCreate(savedInstanceState);  10         setContentView(R.layout.activity_main);  11         // 获取页面中收件人地址、短信内容  12         address = findViewById(R.id.address);  13         content = findViewById(R.id.content);  14         Button bn = findViewById(R.id.send);  15         // 使用外部类的实例作为事件监听器  16         bn.setOnLongClickListener(new SendSmsListener(this,  17                 address.getText().toString(), content.getText().toString()));  18     }  19

 

实际上不推荐将业务逻辑实现写在事件监听器中,包含业务逻辑的事件监听器将导致程序的显示逻辑和业务逻辑耦合,从而增加程序后期的维护难度。如果确实有多个事件监听器需要实现相同的业务逻辑功能,则可以考虑使用业务逻辑组件来定义业务逻辑功能,再让事件监听器来调用业务逻辑组件的业务逻辑方法。

Activity本身作为事件监听器类

 

这种形式使用Activity本身作为事件监听器类,可以直接在Activity类中定义事件处理器方法。这种形式非常简洁,但这种做法有个缺点:这种形式可能造成程序结构混乱,Activity的主要职责时完成界面初始化工作,但是此时还需包含事件处理器方法,从而引起混乱。

 

 1 public class MainActivity extends Activity implements View.OnClickListener   2 {   3     private TextView show;   4     @Override   5     protected void onCreate(Bundle savedInstanceState)   6     {   7         super.onCreate(savedInstanceState);   8         setContentView(R.layout.activity_main);   9         show = findViewById(R.id.show);  10         Button bn = findViewById(R.id.bn);  11         // 直接使用Activity作为事件监听器  12         bn.setOnClickListener(this);  13     }  14     // 实现事件处理方法  15     @Override  16     public void onClick(View v)  17     {  18         show.setText("bn按钮被单击了!");  19     }  20 }  

 

上面的程序让Activity类实现了View.OnClickListener事件监听器接口,从而可以在该Activity类中直接定义事件处理器方法:onClick。当为某个组件添加该事件监听器对象时,直接使用this作为事件监听器对象即可。

 

Lambda表达式作为事件监听器类

 

大部分时候事件处理器都没有什么复用价值(可复用代码通常被抽象成了业务逻辑方法),因此大部分时候事件监听器只是临时使用一次,所以使用Lambda表达式形式的监听器更合适。实际上,这种形式时目前使用最广泛的事件监听器形式。

 

 1 public class MainActivity extends Activity   2 {   3     @Override   4     protected void onCreate(Bundle savedInstanceState)   5     {   6         super.onCreate(savedInstanceState);   7         setContentView(R.layout.activity_main);   8         TextView show = findViewById(R.id.show);   9         Button bn = findViewById(R.id.bn);  10         // 使用Lambda表达式作为事件监听器  11         bn.setOnClickListener(view -> show.setText("bn按钮被单击了!"));  12     }  13 }  

 

上面程序中的粗体字代码使用Lambda表达式创建了一个事件监听器对象,得益于Lambda表达式的简化写法,如果Lambda表达式的执行体只有一行代码,程序可以省略Lambda表达式的花括号。

 

直接绑定到标签

Android还有一种更简单的绑定事件监听器的方式,那就是直接在界面布局文件中为指定标签绑定事件处理方法。界面组件如下:

 1 <TextView   2         android:id="@+id/show"   3         android:layout_width="match_parent"   4         android:layout_height="wrap_content"   5         android:padding="10dp"   6         android:textSize="18sp" />   7        8 <Button   9         android:layout_width="wrap_content"  10         android:layout_height="wrap_content"  11         android:onClick="clickHandler"  12         android:text="单击我" /> 

 

上面的粗体字代码为界面的Button按钮绑定了一个事件处理方法:clickHandler这就意味着开发者需要在该节目布局对应的Activity中定义一个clickHandler方法,该方法将会负责处理该按钮上的单击事件。

MainActivity.java

 1 public class MainActivity extends Activity   2 {   3     private TextView show;   4     @Override   5     protected void onCreate(Bundle savedInstanceState)   6     {   7         super.onCreate(savedInstanceState);   8         setContentView(R.layout.activity_main);   9         show = findViewById(R.id.show);  10     }  11     // 定义一个事件处理方法  12     // 其中source参数代表事件源  13     public void clickHandler(View source)  14     {  15         show.setText("bn按钮被单击了");  16     }  17 }  

注:本博部分内容参考《疯狂Android讲义》一书,侵权必删

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/huangwei1061047046/p/11242601.html

更多相关文章

  1. Android(安卓)对View的一些理解
  2. Android电话系统
  3. 如何使用Android中的OpenGL ES媒体效果
  4. Android中通过反射来设置Toast的显示时间
  5. 简述Unity中调用Android方法
  6. Android(安卓)添加白名单实现保活
  7. 如何使用Android(安卓)UI Fragment开发“列表-详情”界面
  8. 以 Okhttp3源码 为例 ------ 图解 缓存机制 的原理和实现(下)
  9. android webview与H5混合开发,webview自定义缓存

随机推荐

  1. Android最新技术学习笔记
  2. 关于横竖屏切换问题几点知识(Android学习
  3. android的编译和运行过程
  4. Android 上的 Scala, 实战之路(三)——介个
  5. Android开发资料推荐之45个android实例源
  6. 视频播放器
  7. 初入android 下的ndk开发一
  8. 听一名普通android应用开发人员谈:怎样成
  9. android学习日记:关于ActionBar和Menu
  10. Android开发小结Part5:Menu