Android事件处理机制

  一、概述  

  不管是桌面应用还是手机应用,面对的都是用户,经常需要处理用户的操作,为用户的动作提供响应,这种机制就是事件处理

   Androd系统提供了两种事件处理机制

     a、基于监听的事件处理

     b、基于回调的事件处理

二、基于监听的事件处理

    a、涉及三个模型

         Event Source(事件源,事件发生的场所,通俗地讲就是各个组件,如按钮,菜单)(比如企业发生了火灾

         Event(事件),封装了界面上特定的事情(报警,企业处理不了,要消防局来处理)

         EventListener(事件监听器)对事件做出的响应(消防机关的警察来灭火)

       例子:模拟飞机的移动

public class PlaneView extends View{


public float cx;
public float cy;
Bitmap palne;
public PlaneView(Context context){
super(context);
plane=BitmapFactory.decodeResource(context.getResources(),R.drawable.iclon);
setFocusable(true);
}

//还有两个参数,三个参数的构造方法,在使用xml自定义的控件时,会默认调用第二个构造函数
//在这里省略掉了
public void onDraw(Canvas canvas){
super.onDraw(canvas);
Paint p=new Paint();
canvas.drawBitmap(plane,cx,cy,p);
}

 

    主Activity

public class PlaneGame extends Activity{
private int speed=10;//飞机的移动速度
public void onCreate(Bundle savedInstanceState){
super.onCreate();
//去标题
//全屏显示
final PlaneView planeView=new PlaneView(this);
//根据屏幕的宽高设定飞机的初始位置
planeView.cx=....;
planeView.cy=....;
planeView.setOnKeyListener(

      new onKeyListener(){
         public boolean onKey(View source,int keyCode,KeyEvent event){
          //
           //根据event.getKeyCode()来分别控制上下左右
(调整成员变量cx,cy达到改变飞机的位置)       return true;//planeView已经把把键盘触摸的事件消费了,下面的Activity一边待着去吧

}
}
}

);
}
}

 

   三、基于回调的事件处理

定义:相比于监听,回调的事件源和事件监听器统一了,也就是所组件自己就具备处理事件的能力

public class PlaneView extends View{


public float cx;
public float cy;
Bitmap palne;
public PlaneView(Context context){
super(context);
plane=BitmapFactory.decodeResource(context.getResources(),R.drawable.iclon);
setFocusable(true);
}

//还有两个参数,三个参数的构造方法,在使用xml自定义的控件时,会默认调用第二个构造函数
//在这里省略掉了
public void onDraw(Canvas canvas){
super.onDraw(canvas);
Paint p=new Paint();
canvas.drawBitmap(plane,cx,cy,p);
}

//增加的代码,重写按键点击的响应
public boolean onKeyDown(int keyCode,KeyEvent event){
      super.onKeyDown()keyCode,event;
syso("the onkeydown on planeView");
reutrn false;//
}
}

上面在planeview本身就完成了onkeydown的响应

 

事件响应顺序:当组件上的事件被触发后,Android系统最先触发的是按键上绑定的事件监听器,接着才触发该组件提供事件的回调方法,然后传播给该组件的Activity,如果任何一个组件处理返回了true,事件就不会继续向外传播了。

比较者:基于回调的事件处理具备有更加好的内聚性,模块化更加强一点,把属于一个组件的事务封装到一起

在handler里也有回调,因此我们把handler补充进来,形成知识连

四、handler消息传递机制

背景:由于手机的性能是有限的,为了Android性能的优化,(效率高一点),Android的UI操作不是线程安全的(线程安全就是同一个时刻只有一个线程操作数据),这就意味着当多个线程共同操作ui控件的时候可能会线程不安全,于是Android规定:只有UI主线程有权利操作UI组件。

为了实现这样的效果:由于新开辟的线程希望修改属性的值,却没有资格,这个尴尬的局面。Android提供了handler来完成对把控件的值修改的任务(回调的方式处理这个事件)

具体的过程就是:开发者只需要重写handler类的消息处理方法,当新启动线程的消息通过handler会加入的消息队列里,handler源源不断地获取这个消息队列里的消息并且一一处理,于是handler就回调了

介绍了handler 和消息队列,还差一个Looper,它就是消息队列的管理者

handler想源源不断地获取队列的message,就需要当前线程(一般是UI线程)有一个Looper对象

奇怪啊,我们主线程编写是好像没看到过Looper,为什么handler还能正常地运行呢?(因为UI线程已经初始化了Looper对象)。

如果当前线程不是UI线程,而是自己搞的一个子线程,开发者需要创建Looper对象,并且调用prepare()方法,这样handler就能正常地工作了(因为Looper已经管理了消息队列)

对Looper源代码的研究

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

//说明Looper不能通过构造函数实例化,Looper在初始化时会指明哪个消息队列,哪个线程

 

public static final void prepare(){
if(sThreadlocal.get()!=null){
  throw new Exception(一个线程里只能创建一个Looper);
}
sThreadlocal.set(new looper());
}

 threadlocal线程范围内数据共享,类似map集合,键值对,

例子:明天补充

今天复习了两种事件,自定义控件,多线程,handler,挺不错啊,加油

猜你喜欢

转载自1509930816.iteye.com/blog/2247462