本文内容

  • 基于监听的事件模型
  • 基于回调的事件模型

Android 支持两种事件模型,基于监听的事件模型和基于回调的事件模型。

基于监听的事件模型


基于监听的事件模型是一种委托式的,更“面向对象”的事件处理,这跟 Java(或 C#)是一样的。

事件监听处理模型有三个对象:

  • 事件源(Event Source),也就是 GUI 组件。
  • 事件(Event),也就是 Event 对象,GUI 组件上所发生事件的相关信息。
  • 事件监听器(Event Listener),负责监听事件源所发生的事件,并对各种事件做出相应的响应。

其中,事件源最容易创建,任意 GUI 组件都可以作为事件源;事件的产生无须程序员关心,它是由系统自动产生的;而事件监听器是整个事件处理的核心。

例如,当按钮被单击时,该监听器被触发,将在文本框内变为“按钮被单击了”。

public class EventQs extends Activity
{
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // 获取应用程序中的bn按钮
        Button bn = (Button) findViewById(R.id.bn);
        // 为按钮绑定事件监听器。
        bn.setOnClickListener(new MyClickListener()); 
    }
 
    // 定义一个单击事件的监听器
    class MyClickListener implements View.OnClickListener
    {
        // 实现监听器类必须实现的方法,该方法将会作为事件处理器
        @Override
        public void onClick(View v)
        {
            EditText txt = (EditText) findViewById(R.id.txt);
            txt.setText("bn按钮被单击了!");
        }
    }
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

从这个示例看,事件处理模型的步骤:

  • 事件源,就是 ID为 bn 按钮。
  • 事件监听器,MyClickListener 类就是事件监听器,必须由程序员实现。
  • 注册监听器,只要调用事件源的 setOnClickListener 方法即可。

这三件事,事件源可以是任何 GUI 组件,不需要太多程序员参与;注册监听也只要一行代码;因此,事件处理的关键就是事件监听器 MyClickListener。

另外,事件监听器 MyClickListener 本例以一个内部类的形式存在,也可以外部类、Activity 本身作为事件监听器类、匿名内部类。

 

基于回调的事件模型


如果说事件监听机制是一种委托式的事件处理,那么回调机制恰恰相反:对于基于回调的事件处理模型,事件源与事件监听器是统一的,或者说事件监听器完全消失了。当用户在 GUI 组件上触发某个事件时,组件自己特定的方法将会负责处理该事件。

几乎所有基于回调的事件处理方法都有一个 boolean 类型的返回值,该返回值用于标识该处理方法是否能完全处理该事件:

  • 如果返回 true,则表明该处理方法已完全处理该事件,不需要传播
  • 如果返回 false,则表明该处理方法未完全处理该事件,需要传播

对于基于回调的事件传播而言,某组件上所发生的事件不仅仅触发该组件上的回调方法,也会触发该组件所在的 Activity 的回调方法——只要事件能传播到该 Activity。

例如,自定义 Button 控件,重构其 onKeyDown 事件。

public class MyButton extends Button
{
    public MyButton(Context context, AttributeSet set)
    {
        super(context, set);
    }
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event)
    {
        super.onKeyDown(keyCode, event);
        Log.v("-crazyit.org-", "the onKeyDown in MyButton");
        // 返回true,表明该事件不会向外扩散
        return true;
    }
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

对 Android 基于监听的事件处理来说,主要方法是为 Android GUI 组件绑定特定的事件监听器;而对于基于回调的事件处理,主要做法是重写 Android 组件特定的回调方法。

如何选择,一般来说,对于基于回调的事件处理可用于一些通用性的事件,这样代码比较简洁;无法使用基于回调的事件处理时,再采用基于监听的事件处理。

 

下载 内部类作为事件监听器

下载 外部类作为事件监听器

下载 Activity本身作为事件监听器

下载 匿名内部类作为事件监听器

下载 事件绑定到标签

下载 自定义 Button 控件重写 onKeyDown 回调事件

下载 基于回调的事件传播

下载 重写 onTouchEvent 回调事件

Android 事件模型的更多相关文章

  1. Android事件模型之interceptTouchEvnet ,onTouchEvent关系正解

    首先,看Android的官方文档正解 onInterceptTouchEvent()与onTouchEvent()的机制: 1. down事件首先会传递到onInterceptTouchEvent() ...

  2. 对于android触摸事件模型的一些理解

    body{ font-family: "Microsoft YaHei UI","Microsoft YaHei",SimSun,"Segoe UI& ...

  3. 由UI刷新谈到线程安全和Android单线程模型

    1.为什么说invalidate()不能直接在线程中调用? Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在非UI主线程中调用,因为他是违背了单线程模型:A ...

  4. 【Android开发精要笔记】Android组件模型解析

    Android组件模型解析 Android中的Mashup 将应用切分成不同类别的组件,通过统一的定位模型和接口标准将他们整合在一起,来共同完成某项任务.在Android的Mashup模式下,每个组件 ...

  5. 【自己定义控件】android事件分发机制

    自己定义Viewgrou中我们或许会常常碰到这种情况,2个子控件的事件冲突导致滑动没实用了.滑动反应非常慢,点击没用了,要划非常多次才移动一点点等等.或许我们第一反应就是百度,google去搜索下答案 ...

  6. 【朝花夕拾】Android自定义View篇之(六)Android事件分发机制(中)从源码分析事件分发逻辑及经常遇到的一些“诡异”现象

    前言 转载请注明,转自[https://www.cnblogs.com/andy-songwei/p/11039252.html]谢谢! 在上一篇文章[[朝花夕拾]Android自定义View篇之(五 ...

  7. Android事件分发机制三:事件分发工作流程

    前言 很高兴遇见你~ 本文是事件分发系列的第三篇. 在前两篇文章中,Android事件分发机制一:事件是如何到达activity的? 分析了事件分发的真正起点:viewRootImpl,Activit ...

  8. Android事件分发机制浅谈(一)

    ---恢复内容开始--- 一.是什么 我们首先要了解什么是事件分发,通俗的讲就是,当一个触摸事件发生的时候,从一个窗口到一个视图,再到一个视图,直至被消费的过程. 二.做什么 在深入学习android ...

  9. 【repost】JavaScript 事件模型 事件处理机制

    什么是事件? 事件(Event)是JavaScript应用跳动的心脏 ,也是把所有东西粘在一起的胶水.当我们与浏览器中 Web 页面进行某些类型的交互时,事件就发生了.事件可能是用户在某些内容上的点击 ...

随机推荐

  1. linux 内核升级 转

    inux 内核升级 2011-03-25 23:13:28 分类: LINUX 因要测试一些软件,需要2.6.30以上的内核,安装好CentOS 5.5,内核是2.6.18-194.el5.这次的升级 ...

  2. 怎样把XP系统装到USB里?

    怎么样在usb(usb闪存)里面装XP系统? 就是把usb当硬盘用 不买硬盘. U盘肯定装不了系统,装进去了也肯定蓝屏.为什么?因为USB得数据传输太慢,不会超过10M/S的,而你的IDE口或者SAT ...

  3. Xcode工程文件打不开:cannot be opened because the project file cannot be parsed

    svn更新代码后,打开xcode工程文件,会出现  xxx..xcodeproj  cannot be opened because the project file cannot be parsed ...

  4. winform 给textbox 增加 或 减小字体大小 z

    private void btnAddFont_Click(object sender, EventArgs e) { float fSize = this.txtResult.Font.Size; ...

  5. 架构:Eventually Consistent - Revisited

    原文地址:http://i.cnblogs.com/EditPosts.aspx?opt=1. I wrote a first version of this posting on consisten ...

  6. java基础之static(静态)

    静态的属性.方法等属于类而不是对象. 静态的方法能够由类直接调用,不须要将类实例化. 本篇主要说明:1.态的代码.成员变量要比构造方法先运行. 2. 子类的构造方法会默认去调用父类的不带參数的构造方法 ...

  7. 本地docker搭建gitlab, 并配置ldap认证

    基于Docker在Mac OS X系统中的部署和设置GitLab的具体过程如下:   1. 安装Docker for Mac (参见https://docs.docker.com/docker-for ...

  8. Lua的文件操作

    先简单介绍一下被迫使用Lua的IO的情境: 游戏支持玩家自定义上传头像,在排行榜中会显示玩家列表(包括本服.跨服),原有的做法是先检测CCUserDefault中是否存在指定图片的key以及它的状态. ...

  9. Java并发编程的艺术(十)——线程池(1)

    线程池的作用 减少资源的开销 减少了每次创建线程.销毁线程的开销. 提高响应速度 每次请求到来时,由于线程的创建已经完成,故可以直接执行任务,因此提高了响应速度. 提高线程的可管理性 线程是一种稀缺资 ...

  10. 实用ExtJS教程100例-006:ExtJS中Window的用法示例

    在前面几个示例中,我们演示了MessageBox的各种用法,今天这篇文章将演示如何使用Window. 我们首先来创建一个窗口: var win = Ext.create("Ext.windo ...