在做项目的过程中,做了很多回调,好像是一种自然而然的事。回过头来品味,还是十分有趣的。在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中还有很多其它的消息回调机制,我整理下后面会和大家分享。

更多相关文章

  1. Android(安卓)M 动态权限获取
  2. Android下的Service的基本用法
  3. Android版本兼容器
  4. 游走Android系列之Service
  5. Android中 Intent/Bundle传递对象取值为null的剖析以及Serializa
  6. Android第三方应用集成到Android系统的解决方法
  7. android AIDL RPC 机制
  8. android Handler的使用(二)
  9. Android(安卓)JNI和NDK学习(5)--JNI分析API

随机推荐

  1. Android(安卓)4.2官方文档chm格式下载
  2. Android用户界面开发(20):SeekBar
  3. Android(安卓)WebView怎么样嵌套Html
  4. Android底层开发Led控制实验
  5. Android中查看CPU和内存
  6. android分享软件功能的实现
  7. 在Android中创建一种新的输入法
  8. Android(安卓)RIL源码研究笔记 の ril (
  9. android 查看手机存储空间以及文件状态及
  10. android debug工具集