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