siegen程的android技能树之回调函数(callback)

首先,什么是回调函数呢?


回调函数,维基百科上的定义是指通过函数参数传递到其它代码的,某一块可执行代码引用。这段定义看起来很容易让人犯迷糊。


举个例子来说,


有两个函数a,b和主函数c,


主函数c在运行过程中将b的引用传递给了a,这个动作就叫做在a中登记回调函数b。


然后主函数c继续运行,等到a运行(主函数调用或者事件触发)的时候,a调用登记在其中的b,这个动作叫做调用回调函数。


于是函数b开始运行。需要注意的一点是,因为b是由a调用的,所以函数b和函数a运行在同一个线程上。


关于回调函数,知乎上有一段比喻很是生动形象:


你到一个商店买东西,刚好你要的东西没有货,于是你(c)在店员(a)那里留下了你的电话(b),过了几天店里有货了,店员(a)就打了你的电话(b),然后你(c)接到电话后就到店里去取了货。在这个例子里,你的电话号码(b)就叫回调函数,你把电话留给店员(a)就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。
(作者:常溪玲 链接:https://www.zhihu.com/question/19801131/answer/13005983)


现在我们知道了什么是回调函数,那么我们为什么要使用回调函数呢?


笔者大概总结了一下,使用回调函数的应用场景主要有三个。


场景1、函数a属于不可变的代码,它需要你给它提供实现方式函数b,所以这里就需要你将b的引用传递给a。

不可变代码大致有两种:

一是系统的库函数,编程分为两类:系统编程(system programming)和应用编程(application programming)。所谓系统编程,简单来说,就是编写;而应用编程就是利用写好的各种库来编写具某种功用的程序,也就是应用。系统程序员会给自己写的库留下一些接口,即API(application programming interface,应用编程接口),以供应用程序员使用。所以在抽象层的图示里,库位于应用的底下。当程序跑起来时,一般情况下,应用程序(application program)会时常通过API调用库里所预先备好的函数。但是有些库函数(library function)却要求应用先传给它一个函数,好在合适的时候调用,以完成目标任务。这个被传入的、后又被调用的函数就称为回调函数(callback function)。

二是需要将内部细节隐藏起来的函数,只对外面露出接受函数引用的接口,从而增强代码的安全性。


场景2、函数b有很多种实现形式,通过选择在a中登记不同的b来达到动态绑定的效果,使程序更加灵活,降低耦合度。


场景3、用于异步回调的时候。

举个例子,主函数c在主线程中运行,它在a中注册回调函数b。然后启动子线程,并在子线程中运行a。运行的过程中a调用b,因为函数b是在主线程中注册的,所以b会包含主线程的数据,但是它现在却运行在子线程中。这样就完成了线程间通信,由于b中包含主线程的数据,所以大部分的操作都可以在子线程的b中完成,主函数c无需等待子线程的结束,这样就完成了异步调用。


回调函数的实现。

由于笔者学习的是java语言,所以具体来说说关于回调函数在java中的实现。相对于C语言来说,java的回调函数实现稍显麻烦一些,因为C语言中有函数指针,可以直接传递函数指针,java则是通过定义接口来实现回调函数。


具体的实现步骤如下。

  • class A实现接口InA 
  • class A中包含一个class B的引用b 
  • class B有一个参数为InA的方法test(InA a) 
  • A的对象a调用B的方法传入自己,test(a) 
  • 然后b就可以在test方法中调用InA的方法 
1、声明接口InA

public interface InA {   public void method();}


2、class A实现接口InA

<pre name="code" class="java">public class A implements InA
{
    @override
    public void method()
    {
       System.out.println("回调");
    }

    public static void main(String args[])
    {
       B b = new B();
       b.set(new A());
       b.call();
    }
}


 
  
 

class B有一个参数为InA的方法set(InA a)
<span style="font-family: Arial, Helvetica, sans-serif;">public class B</span>
{
    public InA a;

    public void set(InA a)
    {
       this.a= a;
    }

    public void call(){
       this.a.method();
    }
}    


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值