Android事件处理机制有两种:

基于监听的事件处理

基于回调的事件处理。

基于监听的想必学过java或者接触过Android的都了解,最近看了一下有关回调方面的书,今天主要是想说一下基于回调的事件处理机制。多为我自己的理解总结和借鉴别人的一些东西,有错误或者不理解的地方可以在评论处指出来,谢谢~

基于回调事件处理的做法:

重写Android组件特定的回调方法,或者重写activity的回调方法,Android绝大部分界面组件都提供有事件响应的回调方法,开发者只要重写即可。一般的,基于回调的事件处理可用于具有通用型事件,它的代码简洁。

一、回调机制和监听机制

对于基于回调事件处理模型来说事件源与事件监听器是统一的,就是说当用户在GUI组件上激发某个事件时,组件自己特定的方法将负责处理该事件。为了使用回调机制类处理GUI组件上发生的事件,我们需要为该组件提供对应的事件处理方式,但是java是静态语言,我们无法为某个对象动态添加方法,只能继承GUI组件类,然后重写该类的事件处理方法来实现。

为实现回调机制的事件处理,Android为所有GUI组件都提供了一些事件处理的回调方法。以View为例,该类包含如下方法:

boolean onKeyDown(int keyCode,KeyEvent event):当用户在该组件上按下某个按键时触发该方法。

boolean onKeyLongPress(int keyCode,KeyEvent event):当用户在该组件上长按某个按键时触发该方法。

boolean onKeyShortcut(int keyCode,KeyEvent event):当一个键盘快捷键事件发生时触发该方法。

boolean onKeyup(int keyCode,KeyEvent event):当用户在该组件上松开某个按键时触发该方法。

boolean onTouchEvent(MotionEvent event):当用户在该组件上触发触摸屏时触发该方法。

boolean onTrackballEvent(MotionEvent event):当用户在该组件上轨迹球屏事件时触发该方法。

基于回调的事件处理机制可通过自定义View来实现,自定义View时重写该View的事件处理方法即可。

如下例子

自定义Button类:

package com.example.testnoew;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.Button;

public class MyButton extends Button{

public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}

@Override
public boolean onKeyDown(int keyCode,KeyEvent event){

super.onKeyDown(keyCode, event);
Log.v("MYPROJECT", "onKeyDown in MYBUTTON");
//返回TRUE 表明该事件不会向外扩散;
return true;
}
}

xml文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >

<!-- 自定义View用时使用全限定类名 -->
<com.example.testnoew.MyButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click Me"

/>

</RelativeLayout>

然后再activity中调用这个xml文件就好了,接下来运行起来看你的Logcat(不会过滤logcat就自己网上去看),因为重写的MyButton中的onKeyDown消费了点击事件,因此不会传播出去,也就是说按钮会自己处理事件(当然实际开发中这个部分就是我们要自己写东西)。


二、基于回调的事件传播(事件分发机制)

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

如果处理事件的回调方法返回true,表明该处理方法已完全处理该事件(已消费掉)。该事件不会传播出去。

如果处理事件的回调方法返回false,表明该处理方法未完全处理该事件,该事件会传播出去。

对于基于回调的事件传播而言,某组件所发生的事情不仅能够激发该组件的回调方法,也会触发该组件所在的activity的回调方法(只要能够传播到该activity,也就是说某组件不把这个事件消费掉)。

主activity ,重写onKeyDown方法,该方法会在某个按键被按下时被回调

public class MainActivity extends Activity {


private Button testButton;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
testButton = (Button)findViewById(R.id.btn_test);
testButton.setOnKeyListener(new OnKeyListener() {

public boolean onKey(View Source,int kyeCode,KeyEvent event)
{
//只处理按下的事件
if(event.getAction() == KeyEvent.ACTION_DOWN){
Log.i("MYPROJECT", "in Activity Button Listener!");
}
//表明该事件会向外继续传播
return false;
}

});
}

/*
* (non-Javadoc)
* @see android.app.Activity#onKeyDown(int, android.view.KeyEvent)
* onKeyDown方法可监听整个activity包含的所有组件的按键被按下事件
*
*/
public boolean onKeyDown(int keyCode, KeyEvent event){

super.onKeyDown(keyCode, event);
Log.i("MYPROJECT", "in Activity");

return false;

}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}

}

自定义的MyButton类

package com.example.testnoew;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.widget.Button;

public class MyButton extends Button{

public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}

@Override
public boolean onKeyDown(int keyCode,KeyEvent event){

super.onKeyDown(keyCode, event);
Log.v("MYPROJECT", "onKeyDown in MYBUTTON");
//返回false 表明该事件没有被空间本身自己处理,会向外传播;
return false;
}
}

xml文件基本没变,只是给自定义的Button添加了一个id;

通过我们看自己的logcat可以发现当该组件上某个按键被按下的事件发生时,Android系统会最先触发该按键绑定的事件监听器,然后触发该组件提供的事件回调方法,然后会传播到该组件所在的activity中。当然如果我在回调或者事件监听中返回true,那么意味着该事件不会继续向外传播。


三、重写onTouchEvent方法响应触摸屏事件

Android事件处理机制保证基于监听的事件监听器会被有限触发。

基于监听的事件模式分工明确,事件源,事件监听由两个类分开,实现,因此可维护性好点。

基于回调的事件处理机制一定程度上具有高内聚的特性。

具体的实例和上面的大同小异,比如, 我自定义控件,然后再自定义控件内部重写onTouchEvent事件,在这个事件中处理比如位置、大小等变化,然后返回 true,这样所在的activity就不会再处理它。

然后再xml中直接调用这个控件就好了。

本人也是刚工作不到半年,然后这些东西也是看了写书才有所理解,在这里抛砖引玉,有不对的地方欢迎来喷。