【Android应用开发技术:应用组件】事件处理机制

来源:互联网 发布:中国掠夺非洲资源知乎 编辑:程序博客网 时间:2024/05/03 04:54

作者:郭孝星
微博:郭孝星的新浪微博
邮箱:allenwells@163.com
博客:http://blog.csdn.net/allenwells
Github:https://github.com/AllenWells

【Android应用开发技术:应用组件】章节列表

一 事件处理

1.1 基于监听的事件处理

事件监听处理模型

  • 事件源(Event Source):事件发生的场所,通常就是各个组件。
  • 事件(Event):事件封装了界面组件上发生的特定事情。
  • 事件监听器(Event Listener):负责监听事件源所发生的事件,并对各种事件做出相应的响应。

基于监听的事件处理模型的步骤如下所示:

  1. 获取普通界面组件(事件源),也就是被监听的对象。
  2. 实现事件的监听器类。
  3. 调用事件源的setXxxListener()方法将事件监听器对象注册給普通组件(事件源)。

基于监听的事件处理模型有以下两个优点:

  • 基于监听的事件处理模型分工更明确,程序的可维护性好。
  • Android的事件处理机制会保证事件监听器被优先触发。当组件发生某个事件时,系统最先触发的是该按键上绑定的事件监听器,接着才触发该组件提供的事件回调方法。

1.2 事件监听器的实现

1.2.1 外部类作为事件监听器类

应用场合:事件监听器需要要被多个GUI界面所共享,而且主要是完成某种业务逻辑的实现。

1.2.2 Activity作为事件监听器类

这种方式比较简洁,但是Activity主要用来完成界面初始化工作,如果包含了事件处理器方法,会导致程序结构的混乱。

1.2.3 匿名内部类作为监听器类

事件处理器没有复用价值,可以直接用匿名内部类实现。

1.2.4 直接绑定到标签

在布局文件中顶一个onClick属性,该属性对应的属性值是clickHandler的方法名。然后在与布局文件相对应的Activity中定义一个void clickHandler (View source)。

1.3 基于回调的事件处理

事件源和事件监听器是统一的,当事件源发生特定事件以后,该事件还是由事件源本身负责处理。负责处理的方法通常有一个boolean类型的返回值。
如果处理事件的回调方法返回true,表明该方法已完全处理该事件,该事件不会传播出去。
如果处理事件的回调方法返回false,表明该方法不能完全处理该事件,该事件会传播出去。
对于基于回调的事件传播而言,某组件上发生的事件不仅会触发该组件上的回调的方法,还会触发该组件的所在Activity的回调方法(只要事件能够传播到Activity)。

1.4 Handler消息传递机制

出于性能优化考虑,Android的UI操作并不是线程安全的,为了解决多线程并发UI操作可能导致的线程安全问题,Android规定:只允许UI线程修改Activity里的组件。
UI线程(主线程Main Thread):一个程序第一次启动时,Android同时启动的一条主线程,用来处理与UI相关的事件。
Handler可以分发Message对象和Runnale对象到主线程中,每个Handler实例都会绑定到创建它的线程(一般是主线程)。
Handler分发消息的方法。

  • post(Runnable);
  • postAtTime(Runnable, long);
  • postDelayed(Runnable, long);

post方法允许你排列一个Runnable对象到主线程队列中。

  • sendEmptyMessage(int);
  • sendMessageAtTime(Message, long);
  • sendMessageDelayed(Message, long);

sendMessage方法允许安排一个带数据的Message对象到队列中,等待更新。

1.4.1 Handler类

Handler类的主要作用有两个:

  • 在新启动的线程中发送消息。
  • 在主线程中获取和处理消息。

Handler使用步骤如下所示:

  1. 调用Looper的prepare()方法为当前线程创建Looper对象,创建Looper对象时,它的构造器会创建与之配套的MessageQueue对象。
  2. 创建Handler类子类的实例,重写HandleMessage()方法,该方法用来处理来自于其他线程的消息。
  3. 调用Looper的loop()方法启动Looper。

1.4.2 Looper类

每个线程只能有一个Looper,它的loop()方法负责读取MessageQueue中的消息,读到信息之后就把消息交给发送该消息的Handler进行处理。

Looper的构造方法如下所示。

private Looper(){        mQueue = new MessageQueue();        mRun = true;        mThread = Thread.currentThread();}

为了保证当前线程有Looper对象,可以分为以下两种情况处理。

  1. 主UI线程中,系统已经初始化了一个Looper对象,因此程序直接创建Handler对象即可,然后调用Handler对象发送消息和处理消息。
  2. 程序员自己启动的子线程,程序员必须自己创建一个Looper对象,并启动它。创建Looper对象可由prepare()方法进行,该方法保证每个线程最多只有一个Looper对象。

1.4.3 MessageQueue类

消息队列,它采用先进先出的方式管理Message。

1.5 异步任务

异步任务AsyncTask是一个抽象类,它有以下三种泛型。

  • Params:启动任务执行的输入参数类型。
  • Progress:后台任务完成的进度值的类型。
  • Result:后台执行任务完成后返回结果的类型。

创建AsyncTask 的步骤如下所示:

  1. 创建AsyncTask的子类,并为三个泛型参数指定类型。对于不需要指定类型的泛型参数可指定为void。
  2. 根据需要实现以下方法。

  3. doInBackground (Params…):后台线程将要完成的任务,该方法可以调用publishProgress (Progress… values)方法来更新任务的执行进度。调用该方法后将会触发onProgress ()方法。

onPreExecute ():该方法用于完成一些初始化的准备工作,通常在执行后台耗时操作前被调用。

onPostExecute (Result result):当doInBackground()完成后,系统会自动调用该方法,并将doInBackground()方法的返回值传给该函数。

  1. 调用AsyncTask子类的实例的execute (Params … params)开始执行耗时任务。
  2. 使用AsyncTask时必须遵守以下规则:

    • 必须在UI线程中创建AsyncTask的实例。
    • 必须在UI线程中调用AsyncTask的execute()方法。
    • AsyncTask的onPreExecute(),onPostExcute(Result result),doInBackground (Params… paras),onPrograssUpdate(Prograss… values)方法,不应该由程序员代码调用,而是由Android系统调用。
    • 每个AsyncTask只能被执行一次,多次调用会引发异常。
0 0
原创粉丝点击