Android的事件处理---监听机制和回调机制-总结
Android有两种方式的事件处理:
1、基于回调的事件处理 2、基于监听器的事件处理
一、先来大概说明一下监听器的事件处理的实现原理
(学过AWT 、Swing的同学对监听器基本有一点了解。)
===》》》 监听事件是一种“面向对象”的事件处理 《《《===
涉及三类对象:
- Event Source(事件源): 也就是按钮,菜单,窗口等
- Event(事件):就是操作的状态,单击、触摸、长按、双击等
- Event Listener(事件监听器):对用户的操作做出响应,也就是单击按钮了使他有反应
既然他们都是独自的对象,处理方式也就比较宽泛。一个监听器中可以有多个事件被监听
public class MainActivity extends Activity { private Button button1, button2, button3; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button1 = (Button) findViewById(R.id.button1); button2 = (Button) findViewById(R.id.button2); button3 = (Button) findViewById(R.id.button3); button1.setOnClickListener(listener); button2.setOnClickListener(listener); button3.setOnClickListener(listener); } private OnClickListener listener = new OnClickListener() { @Override public void onClick(View view) { switch (view.getId()) { case R.id.button1: Toast.makeText(MainActivity.this,"点击了button1", 1).show(); break; case R.id.button2: Toast.makeText(MainActivity.this,"点击了button2", 1).show(); break; case R.id.button3: Toast.makeText(MainActivity.this,"点击了button3", 1).show(); break; } } }; }
通过view.getId()来获取不同的组件,switch来判断不同组件的事件
当然,一个事件源也可以有多个不同的监听器监听不同的事件,菜单可以有单击事件,也可以有长按事件。
有个有意思的比喻:说android的事件处理机制是一种委派式事件处理方式,普通UI组件将发生的事件交给监听器去处理,自己不处理。好比如:发生火灾了,交给消防局处理,发生打架了交给公安局处理,并且消防局和公安局又可以同时处理多个火灾和打架事件。 这样的委派式处理方式提高了程序的可维护性。挺好。
====》》》 实现监听器的5种形式 《《《===
1、内部类形式,此时监听器可以被复用,监听器还可以自由访问外部类中所有界面组件
2、外部类形式(这种方式少见),首先不利于提高程序内聚性,而且监听器也不能自由访问界面中组件。当然也有用到的时候,比如某个监听器需要被多个GUI界面所共享的时候。
3、Activity本身作为监听器(更少见),implements OnClickListener (特例)就可以实现
4、匿名内部类(使用广泛),
button.setOnClickListener(new OnClickListener(){
@override
Public void onClick(View v){
}
}
);
注意: new的监听器可以放在方法的括号中,当多个按钮需要实现这种监听时可以拿出来,制定给某个变量,(上面介绍的一个监听器中可以有多个事件被监听的代码就是这样)
5、还可以直接绑定到标签
比如Button的一个属性 android:onClick=“clickHandler”
接下来实现一个clickHandler方法就可以了、注意要传一个View参数,不然没有反应 View形参代表被单击的UI组件。
Public void clickHandler( View source) { }
二、 下面说一下基于回调的事件处理
1、上面的监听机制是一种委托式处理,那么回调机制则相反,回调机制则是发生某个事件时UI组件自己处理事件。
(貌似基于回调的事件处理是用在自定义的UI组件中)
自定义某个组件然后继承该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时,要用全限定类名(包名.类名),
有个简单方法:将鼠标光标放在自定义类上面,将出现的框中内容直接复制就行
2、基于回调事件的传播
所有基于回调的事件处理方法都有一个boolean类型的返回值,该返回值用于标识该处理方法能否完全处理该事件
True : 表示该处理方法已完全处理该事件,事件不会传播出去
False: 没有完全处理该事件,事件会传播出去
既然要传播,都传向哪里呢,下面介绍
有3个地方需要返回boolean类型,也就是事件是否完全处理
(1) 自定义组件重写的回调方法return一个
1 import android.content.Context; 2 import android.util.AttributeSet; 3 import android.util.Log; 4 import android.view.KeyEvent; 5 import android.widget.Button; 6 7 public class MyButton extends Button 8 { 9 public MyButton(Context context , AttributeSet set) 10 { 11 super(context , set); 12 } 13 @Override 14 public boolean onKeyDown(int keyCode, KeyEvent event) 15 { 16 super.onKeyDown(keyCode , event); 17 Log.v("--MyButton--" , "the onKeyDown in MyButton"); 18 // 返回false,表明并未完全处理该事件,该事件依然向外扩散 19 return false; 20 } 21 }
(2) 绑定监听机制实现的事件处理方法中 return 一个
1 @Override 2 public void onCreate(Bundle savedInstanceState) 3 { 4 super.onCreate(savedInstanceState); 5 setContentView(R.layout.main); 6 Button bn = (Button) findViewById(R.id.bn); 7 // 为bn绑定事件监听器 8 bn.setOnKeyListener(new OnKeyListener() 9 { 10 @Override 11 public boolean onKey(View source 12 , int keyCode, KeyEvent event) 13 { 14 // 只处理按下键的事件 15 if (event.getAction() == KeyEvent.ACTION_DOWN) 16 { 17 Log.v("-Listener-", "the onKeyDown in Listener"); 18 } 19 // 返回false,表明该事件会向外传播 20 return true; // ① 21 } 22 }); 23 }
(3) Activity中重写回调方法,return一个
1 // 重写onKeyDown方法,该方法可监听它所包含的所有组件的按键被按下事件 2 @Override 3 public boolean onKeyDown(int keyCode, KeyEvent event) 4 { 5 super.onKeyDown(keyCode , event); 6 Log.v("-Activity-" , "the onKeyDown in Activity"); 7 //返回false,表明并未完全处理该事件,该事件依然向外扩散 8 return false; 9 }
下面说一下传播的顺序:
传播顺序是:首先传播到组件绑定的监听器上,然后是自定义组件重写的事件方法,最后传播到组件所在Activity,当然,如果任何一个返回了true,那么事件将不会继续向外传播。