Android的事件处理

3.1 Android提供了两套事件处理机制:基于监听的事件处理、基于回调的事件处理。

3.2 基于监听的事件处理

3.2.1 监听的处理模型  主要涉及三类对象:EventSource、Event、EventListener。

Android的事件处理机制是一种委派式(Delegation)事件处理方式:普通组件将整个事件处理委托给特定的对象(事件监听器),可以把所有可能的事件授权给不同的事件监听器来处理,也可以让一类事件都使用同一个事件监听器来处理。

事件监听类是一个特殊的类,必须实现某Listener接口。

3.2.2 事件和事件监听器  如果事件足够简单、事件里封装的信息有限,那就无需封装事件对象、将事件对象出入事件监听器。但对于键盘事件、触摸屏事件,程序需要获取事件发生的详细信息,Android会把事件信息封装成xxxEvent对象,并传给事件监听器。

(源码\03\3.2\plane) 增加触摸事件:

planeView.setOnTouchListener(new View.OnTouchListener(){

@Override public boolean onTouch (View v, MotionEvent event)

......

说明:planeView所使用的事件监听器类是内部类,使用内部类可以在当前类中复用该监听器类;因为监听器类是外部类的内部类,所以可以自由访问外部类的所有界面组件。这也是内部类的两个优势。

3.2.4 外部类作为事件监听器类  这种形式比较少见,因为不利于提高程序的内聚性,不能自由访问创建GUI界面的类中的组件。但如果某个监听器确实需要被多个GUI界面所共享,而且主要完成某种业务逻辑的实现,则可以考虑用外部类的形式定义事件监听器类。

(源码\03\3.2\SendSms)

3.2.5 Activity本身作为事件监听器, 形式简单,但因为Activity的主要职责应该是完成界面初始化工作,界面类需要实现事件监听处理,比较奇怪,容易引起混乱。

3.2.6 匿名内部类作为事件监听器类, 这种形式是目前使用最广泛的事件监听器形式,因为事件处理器的复用价值不大。

3.2.7 直接绑定到标签,直接在界面布局文件中为指定标签绑定事件处理方法。

3.3 基于回调的事件处理

3.3.1 回调机制 对于这种事件处理模型,事件源和事件监听器是统一的,没有事件监听器了。Android为所有GUI组件都提供了一些事件处理的回调方法。继承GUI组件类,并重写该类的事件处理方法。

3.3.2 基于回调的事件传播 几乎所有基于回调的事件处理方法都有一个Boolean类型的返回值,如果返回true,表明该方法已完全处理该事件,该事件不会传播出去;如果返回false,表明该方法并未完全处理该事件,该事件会传播出去,会触发该组件所在Activity的回调方法。

3.3.3 对比

基于监听的事件处理模型具有的优势:分工明确,事件源、事件监听由两个类分开实现,由更好的可维护性;基于监听的事件监听器会被优先触发。

基于回调的事件处理机制的优势:可以更好地提高程序的内聚性。

3.4 响应系统设置的事件

监听系统设置的更改,对系统设置的更改做出响应。如:判断屏幕方向、系统方向的方向导航设备。

3.4.1 Configuration类 专门用户描述设备上的配置信息,既包括用户特定的配置项,也包括系统的动态设备配置。

3.4.2 重写Activity的onConfigurationChanged方法,响应系统设置更改,这个方法是基于回调的事件处理方法。

3.5 Handler消息传递机制

Android的UI操作不是线程安全的,Android的规则是:只允许主线程(UI线程,第一次启动时创建的) 修改Activity里的UI组件。如果新启动的线程需要动态修改界面组件的属性值,需要借助于Handler的消息传递机制来实现。

3.5.1 Handler类的主要作用:在新启动的线程中发送消息,在主线程中获取、处理消息。主线程只能通过回调的方式来适时处理其它线程发生的消息。(源码\03\3.5\HandlerTest)

2.5.2 Handler、Looper、MessageQueue的工作原理: 一个线程只能有一个Looper对象,Looper负责管理MessageQueue,Looper对象会创建MessageQueue,MessageQueue采用先进先出的方式管理消息;主UI线程中,系统为其初始化了一个Looper对象,因此程序直接创建Handler即可;程序员启动的子线程,必须自己创建一个Looper对象,并调用它的prepare()方法和loop()方法启动它即可。(源码\03\3.5\CalPrime)

尽量避免在UI线程中执行耗时操作,因为这可能导致一个“著名”的 异常:ANR异常,应用无法响应输入事件和Broadcast。Android默认约定当UI线程阻塞超过20秒将会引发ANR异常。

3.6 异步任务 AsyncTask

AsyncTask 适用于简单的异步处理,是轻量级的,不需要借助线程和Handler即可实现。

AsyncTask<Params, Progress, Result> 是抽象类,它定义了如下三种泛型类型:Params是启动任务执行的输入参数,Progress是后台任务完成的进度值,Result是后台任务完成后的返回结果。

使用AsyncTask需要创建它的子类,并根据需要实现相关方法。

(源码\03\3.6\AsyncTaskTest)

使用AsyncTask时必须遵守的规则:必须在UI线程中创建它的实例;必须在UI线程中调用它的execute()方法;AsyncTask的onPreExecute()、onPostExecute()等方法只能由Android系统负责调用;每个AsyncTask只能被执行一次。

疯狂Android讲义 - 学习笔记(三)的更多相关文章

  1. 疯狂Android讲义 - 学习笔记(二)

    Android应用的用户界面编程 2.1 界面编程与视图(View)组件 Android应用的绝大部分UI组件放在android.widget.android.view包及其子包中,所有UI组件都继承 ...

  2. 疯狂Android讲义 - 学习笔记(一)

    常用开发工具的用法 android : 启动Android SDK管理器 android --help  查看具体用法 android create avd -n t10 -t 10 -b armea ...

  3. 疯狂Android讲义 - 学习笔记(八)

    第10章 Service与BroadcastReceiver 10.1 Service简介 Service组件也是可执行的程序,有自己的生命周期,创建.配置Service与创建.配置Activity的 ...

  4. 疯狂Android讲义 - 学习笔记(七)

    第8章 Android数据存储与IO  Java IO的数据存储可以移植到Android应用开发上来,Android系统还提供了一些专门的IO API. Android系统内置了SQLite数据库,S ...

  5. 疯狂Android讲义 - 学习笔记(六)

    第7章 7.1 使用简单图片 7.1.1 使用Drawable对象 7.1.2 Bitmap和BitmapFactory 7.2 绘图 7.2.1 Android绘图基础:Canvas.Paint等 ...

  6. 疯狂Android讲义 - 学习笔记(五)

    第五章 Android使用统一的Intent对象来封装“启动意图”,不管是启动Activity.Service组件.或者BroadcastReceiver等,提供了一致的编程模型.Intent设计有点 ...

  7. 疯狂Android讲义 - 学习笔记(四)

    Android应用通常有多个Activity,多个Activity组成Activity栈,当前活动的Activity位于栈顶.Activity相当于Java Web开发的Servlet.当Activi ...

  8. 【疯狂Java讲义学习笔记】【流程控制与数组】

    [学习笔记]1.switch语句后的expression表达式的数据类型只能是byte.short.char.int四个整数类型.String(Java 7后才支持)和枚举类型. 2.数组的长度不可变 ...

  9. 【疯狂Java讲义学习笔记】【数据类型与运算符】

    [学习笔记]1.8bit = 1byte,4byte = 1word.Java中的整型数据有byte(1字节),short(2字节),int(4字节),long(8字节).Java中的浮点数据有flo ...

随机推荐

  1. Linux 挂载管理(mount)

    标签:mount,umount 概述 在上一章增加linux操作系统空间中已经使用过了mount命令对分区进行挂载,这一章详细介绍挂载管理,该命令涉及的知识点也挺多的而且也还比较重要,是需要掌握的一个 ...

  2. dubbo 配置文件详解

    一.dubbo常用配置 <dubbo:service/> 服务配置,用于暴露一个服务,定义服务的元信息,一个服务可以用多个协议暴露,一个服务也可以注册到多个注册中心. eg.<dub ...

  3. Angularjs学习---官方phonecat实例学习angularjs step0 step1

    接下来一系列的文章都是学习https://docs.angularjs.org/tutorial的笔记,主要学习的angular-phonecat项目的实现,来介绍angularjs的使用. 1.下载 ...

  4. C语言-结构体struct-联合体union-枚举enum

    结构体 在Java中,我们要表示一个复合的数据类型就会使用对象去封装.而C就有结构体. 结构体是C语言中自定义的数据类型,是一组变量的集合,有别于数组,数组仅限于同一种数据类型,而结构体可以是任何数据 ...

  5. HTML5应用缓存机制

    首先先上一张图: 用360浏览器的用户对这张图应该都是耳熟能详了吧,没错,当网络不通畅时使用360浏览器,便会有这张图弹出来.为什么没有网络还能弹出这一副画面呢?这就关乎HTML5的应用缓存机制了. ...

  6. lua中的数据类型

    lobject.h: lobject.h: 其中使用GCObject表示的数据类型是需要lua 的gc记录的. lstate.h: lobject.h:

  7. v-if VS v-show

    在vue实现轮播图效果 中分别用到 v-if和 v-show 下面讲讲我理解的他们的区别: v-if: 根据表达式的值的真假条件渲染元素.在切换时元素及它的数据绑定 / 组件被销毁并重建.如果元素是 ...

  8. 如何用Python实现杨辉三角和心

    1. 如何实现杨辉三角 import copy list=[] newlist=[] def Fibonacci(list,n): newlist.append(0) if n ==1: return ...

  9. JavaScript sync and async(同步和异步)

    推荐四篇文章: JavaScript 是单线程的深入分析 JavaScript 运行机制详解:再谈 Event Loop JavaScript 异步编程的4种方法 JavaScript 既是单线程又是 ...

  10. 【记录】T-SQL 分组排序中取出最新数据

    示例 Product 表结构: 示例 Product 表数据: 想要的效果是,以 GroupName 字段分组,取出分组中通过 Sort 降序最新的数据,通过示例数据,可以推算出结果数据的 ID 应该 ...