JAVA回调机制
事件处理中经常使用到回调机制。其使用方法大致如下:
(1)新建立一个接口类,标志需要处理哪一类事件
package com.bobo.mycallback; //定义一个接口,里面实现一个普通的方法 public interface MyEvent { public void doSomething(); }
(2)需要处理该事件的类都需要实现这个接口
类一,定义事件接口
public class MyEventImpl1 implements MyEvent { private String name; public MyEventImpl1(String name){ this.name=name; } @Override public void doSomething() { System.out.println("我是MyEventImpl1类:"+name+",我是我实现了回调接口,是事件处理类"); } }
类二、所有的事件源都需要实现事件接口
public class MyEventImpl2 implements MyEvent { private String name; public MyEventImpl2(String name){ this.name=name; } @Override public void doSomething() { System.out.println("我是MyEventImpl2类:"+name+",我是我实现了回调接口,是事件处理类"); } }
三、定义事件通知者类:
如果通知者仅需要通知一个事件处理类,则需要含有一个事件接口的成员变量,一个为该成员变量赋值的方法以及调用该接口对象事件处理函数的方法
package com.bobo.mycallback; public class EventNotifier2 { MyEvent event; //如果只有一个事件而不是一个事件序列的话 public void setEvent(MyEvent event){ this.event=event; } public void doMyWork(){ event.doSomething(); } }
如果通知者需要通知一系列的时间处理类,则需要含有一个list<事件接口>的成员变量,一个为该成员变量赋值的方法以及调用该接口对象事件处理函数的方法
package com.bobo.mycallback; import java.util.ArrayList; //这个类是充当的是事件通知者的角色 public class EventNotifier { private ArrayList<MyEvent> events=new ArrayList<MyEvent>(); public void register(MyEvent ev){ events.add(ev); } public void doWork(){ for(MyEvent ev : events){ ev.doSomething(); } } public EventNotifier(){ } }
接受事件的类中,需要具有事件通知者这个成员变量,当触发事件的条件发生的时候,调用通知者处理事件的函数(这里以测试类为例)
package com.bobo.mycallback; import android.os.Bundle; import android.app.Activity; import android.view.KeyEvent; import android.view.Menu; public class MainActivity extends Activity { EventNotifier notify = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 这个类里面触发事件 MyEventImpl1 impl = new MyEventImpl1("impl1"); MyEventImpl1 imp2 = new MyEventImpl1("impl2"); // 借助于事件通知来实现 notify = new EventNotifier(); notify.register(impl); notify.register(imp2); // 当发生某个时间的时候,这里假设按下返回键的时候触发 notify.doWork(); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { boolean isHandled = false; if (keyCode == KeyEvent.KEYCODE_BACK) { notify.doWork(); } return isHandled; } }
或者对于仅仅只有一个事件源的监听者,其测试如下:
package com.bobo.mycallback; import android.os.Bundle; import android.app.Activity; import android.view.KeyEvent; import android.view.Menu; public class MainActivity extends Activity { EventNotifier2 notify = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 这个类里面触发事件 MyEventImpl1 impl = new MyEventImpl1("impl1"); // 借助于事件通知来实现 notify = new EventNotifier2(); notify.setEvent(impl); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { boolean isHandled = false; if (keyCode == KeyEvent.KEYCODE_BACK) { notify.doMyWork(); } return isHandled; } }
但是需要注意的是,事件接口、事件处理类(实现事件接口的类)、事件通知者(为事件接口赋事件源、调用事件接口方法的类)、事件源(触发事件的类《如这里的测试类》);这未必是严格意义上的四个类。
有时候一个类可以同时充当事件测试类、事件通知者、事件接口等多个角色。这些角色可以以成员变量、成员方法、内部类等方式来存在;除了充当这些角色,这些类本身可能还具有很多其他功能。
比如在绿萝天气的项目中,为了完成日历单元格的点击事件,
DateWidgetDayCell这个类就充当了事件源、事件接口、事件通知者三个角色
而CalendarActivity则相当于事件处理类的角色
此外两个类还都实现了很多其他功能。
注意不要拘泥于这种形式,
例如:时间处理对象可能不是一个实现了事件接口的类,也可能是个匿名内部类作为函数调用的参数。但机制应当明白。