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中直接调用这个控件就好了。
本人也是刚工作不到半年,然后这些东西也是看了写书才有所理解,在这里抛砖引玉,有不对的地方欢迎来喷。
https://blog.51cto.com/poarry/1554560