Android接口回调,最简单的理解方式
在做项目的过程中,做了很多回调,好像是一种自然而然的事。回过头来品味,还是十分有趣的。在Android中为什么定义那么多接口,很大一部分都是用来接口回调的,包括那些OnListener等系统给出接口都是这种用法。
1.Java中的回调函数
理解一个东西,必须从它的本源入手,再实例化到生活事例中,加深理解,毕竟程序是对现实生活的一种抽象。
而Android中的回调,遵循的基本思想是Java中的回调函数。
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
Java 中没有指针的概念,通过接口和内部类的方式实现回调的功能:
1. 定义接口 Callback ,包含回调方法 callback()
2. 在一个类Caller 中声明一个Callback接口对象 mCallback
3. 在程序中赋予 Caller对象的接口成员(mCallback) 一个内部类对象如
new Callback(){
callback(){
//函数的具体实现
}
这样,在需要的时候,可用Caller对象的mCallback接口成员 调用callback()方法,完成回调.
Talk is cheap,show me the code!
现在就上代码来讲解,这是基于本例子的讲解。
public class Test{ // 方法是fun public static void fun(Callbackinterface ci){ ci.callbackfun(); } //这就是接口 public interface Callbackinterface{ public void callbackfun(); }}public static void main(){ // 调用fun,传入接口对象并构造内部类 Test.fun(new Callbackinterface( public void callbackfun(){ //你的实现 } ) );}
看完这个,大家可能还会比较模糊,没关系。我再讲一个实例:
一项工程由程序员A和B共同完成,分别负责不同的模块,模块之间有交叉,A和B可能用到对方的方法,这时需要进行回调。
假设我是程序员A,写了一个程序a:
public class Caller { private MyCallInterface mc; //构造函数 public Caller() { } public setI(MyCallInterface mc) { this.mc = mc; } //Caller的调用方法 public call() { mc.fuc(); }}
这里需要定义一个接口,以便程序员B根据我的定义编写程序实现接口。
public interface MyCallInterface { public void fuc();}
于是,程序员B只需要实现这个接口就能达到回调的目的了:
public class callee implements MyCallInterface { public void fuc() { //do something }}
下面是调用过程:
public class callbacks { public static void main(String args[]) { Callee c1 = new Callee(); Caller caller = new Caller(); caller.setI(c1); caller.call(); }}
在以上代码中,caller是调用者,callee是被调用者,callbacks表示调用过程。
先产生了Callee对象(已经实现Caller提供的接口),利用这个callee对象产生的Caller对象则携带了一些信息(即与Callee对象的关联,因为Callee对象已经作为参数传入),所以Caller对象可以利用自己的call方法调用Callee的方法。——这就是整个回调过程。
看了这个例子,想必大家已经清楚了Java回调函数的机制了吧。
现在来总结一下,一般来说分为以下几步:
1. 声明回调函数的统一接口interface A,包含方法fuc();
2. 在调用类caller内将该接口设置为私有成员private A XXX;
3. 在caller内提供一个public方法,可以将外部“该接口A的实现类的引用”通过形参传给XXX;
4. caller的某个方法call()中会用到XXX.fuc()方法;
5. 在caller的实例中,将实现了A接口的对象的引用传给caller,后调用call()方法
2.Android的回调
Android中回调是用得非常多的。比如点击事件,Activity的生命周期等等,这里的回调大多更是一种触发机制,可以说回调也是一种触发吧。
例如Button是设置了接口,接口就是OnListener,在onClick中我们写入自己的实现,然后系统在事件被触发后调用。我们自己不会显式地去调用onClick方法。用户触发了该按钮的点击事件后,它会由Android系统来自动调用。
下面模拟一下Activity生命周期,基本都是回调函数在作用:
1. Activity接口
//定义接口 public interface Activity{ //创建时调用的方法 public void onCreate(); //启动时调用的方法 public void onStart(); //销毁时调用的方法 public void onDestory(); }
2. Activity接口的实现类MyActivity
//定义一个类实现Activity接口 public void MyActivity implements Activity{ //实现创建方法,简单输出提示信息 @Override public void onCreate(){ System.out.println("onCreate...."); } //实现启动方法,简单输出提示信息 @Override public void onStart(){ System.out.println("onStart...."); } //实现销毁方法,简单输出提示信息 @Override public void onDestory(){ System.out.println("onDestory...."); } }
3. 系统运行环境类AndroidSystem
//系统运行环境类 public class AndroidSystem{ //定义创建常量 public static final int CREATE=1; //定义启动常量 public static final int START=2; //定义销毁常量 public static final int DESTORY=3; //运行方法 public void run(Activity a,int state){ switch(state){ //创建 case CREATE: a.onCreate(); break; //启动 case START: a.onStart(); break; //销毁 case DESTORY: a.onDestory(); break; } } }
测试类:
//测试类 public class Test{ //主方法 public static void main(String[] args){ //实例化AndroidSystem AndroidSystem system = new AndroidSystem(); //实例化MyActivity Activity a = new MyActivity(); //创建 system.run(a,AndroidSystem.CREATE); //启动 system.run(a,AndroidSystem.START); //销毁 system.run(a,AndroidSystem.DESTORY); } }
通过上述代码我们可以看出,接口(系统框架)是系统提供的,接口的实现是用户实现的。这样可以达到接口统一,实现不同。系统通过在不同的状态“回调”我们的实现类,来达到接口和实现的分离。
这里引用其它人博客的一个事例吧:
让我们从一个小故事开始。
某天,我打电话向你请教问题,当然是个难题,你一时想不出解决方法,我又不能拿着电话在那里傻等,于是我们约定:等你想出办法后打手机通知我,这样,我就挂掉电话办其它事情去了。过了XX分钟,我的手机响了,你兴高采烈的说问题已经搞定,应该如此这般处理。
OK,这个故事我们先告一段落,其实,这就是一个典型的回调过程。
而在程序代码中,则可以抽象成以下这张图的形式:
C不会自己调用b,C提供b的目的就是让S来调用它,而且C不得不提供。S并不知道C提供的b是什么,因此S会约定b的接口规范(函数原型),然后由C提前通过S的一个函数r告诉S自己将要使用b函数(即注册),比如注册监听器就是其中一种典型。其中r为注册函数。
对上图的一个完善是这样的:
Android中还有很多其它的消息回调机制,我整理下后面会和大家分享。
更多相关文章
- Android(安卓)M 动态权限获取
- Android下的Service的基本用法
- Android版本兼容器
- 游走Android系列之Service
- Android中 Intent/Bundle传递对象取值为null的剖析以及Serializa
- Android第三方应用集成到Android系统的解决方法
- android AIDL RPC 机制
- android Handler的使用(二)
- Android(安卓)JNI和NDK学习(5)--JNI分析API