关于回调函数的理解

回调函数


更新:2017-1-22


这里写图片描述

网上关于回调函数的例子很多。以下下是我的理解:

  • 神话版:调用,回调。
  • 直述版:A让B做某事,B做着做着发现:哎呀,不对呀,这事具体应该怎么做呀?于是,回调A中询问事件具体的实现形式。然后完成事件。——以同步回调的角度(或者理解:这事我做完了接下该你A来做了,于是回调A的方法——以异步回调的角度)
  • 抽象版:首先A有某事要完成,分为动作①和动作②。A让B做某事的动作①(在B中实现动作①),B做完之后回调A 某事中的动作②(在A中实现,A懒得做了,提供方法想让B给他完成)。完成整个某事。(简之:a调用了b的方法,b开始执行,b执行完了,再调用a的方法。)
    *注意:A调用B,B执行完后返回A → 只是简单的调用,没有涉及到回调,即没有回调函数的实现。
  • 具体版:有A和B两类(A看成应用程序,B看成系统),A调用B的方法Bf实现动作(A可以在Bf传入相关信息,★其中包括A的引用)。Bf的方法在执行完成后,因为有了A的引用,可以回调A的Af方法。Af方法就是回调函数,用来展示,或者说完成某事。
  • 终极版: 上述在回调函数中直接传入对象的引用。产生的问题(Bf方法的形参里有A的引用):①暴露了对象,即传入了A的引用(B系统得到了A的引用,万一B是竞争对手呢,不安全);②增加了耦合性,每有一个新的A出现需要重写Bf方法(因为形参需要改变)。终极大招:接口方式的回调方法。——首先定义接口,A1、A2、A3。。。可以各自实现接口,相当于有不同的动作②(此时的Af是基于接口的实现方法)。A调用B的Bf方法完成动作①后,Bf回调A中方法Af(Bf的形参现在是接口,B干不了坏事了)。
  • (彩蛋)实用主义:匿名内部类。直接在方法Af实现接口。

eg:https://www.zhihu.com/question/19801131/answer/26586203


同步与异步

同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication)

  • 所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了。
    换句话说,就是由调用者主动等待这个调用的结果。

  • 异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用。

  • 异步回调
    异步回调有点像中断调用。在A中开线程调用B,然后做自己的事。等B处理完回调A。

  • 同步回调
    A一直等B的回调。

实现场景

例1:打个比方,有一家旅馆提供叫醒服务,但是要求旅客自己决定叫醒的方法。可以是打客房电话,也可以是派服务员去敲门,睡得死怕耽误事的,还可以要求往自己头上浇盆水。这里,“叫醒”这个行为是旅馆提供的,相当于库函数,但是叫醒的方式是由旅客决定并告诉旅馆的,也就是回调函数。而旅客告诉旅馆怎么叫醒自己的动作,也就是把回调函数传入库函数的动作,称为登记回调函数
eg:https://www.zhihu.com/question/19801131/answer/27459821
来源:知乎
著作权归作者所有,转载请联系作者获得授权。
解释了回调函数在实际中的意义。


例2:你到一个商店买东西,刚好你要的东西没有货,于是你在店员那里留下了你的电话,过了几天店里有货了,店员就打了你的电话,然后你接到电话后就到店里去取了货。在这个例子里,你的电话号码就叫回调函数,你把电话留给店员就叫登记回调函数,店里后来有货了叫做触发了回调关联的事件,店员给你打电话叫做调用回调函数,你到店里去取货叫做响应回调事件。回答完毕。

作者:常溪玲
链接:https://www.zhihu.com/question/19801131/answer/13005983
来源:知乎
著作权归作者所有,转载请联系作者获得授权。
异步回调。A:我;B:店员。买东西事件分为两个行动,行动①:找货,A调用B执行;行动②:打电话,B回调A的电话号码。


例3:一个经典例子让你彻彻底底理解java回调机制
来源:http://blog.csdn.net/xiaanming/article/details/8703708/

3.1 有一天小王遇到一个很难的问题,问题是“1 + 1 = ?”,就打电话问小李,小李一下子也不知道,就跟小王说,等我办完手上的事情,就去想想答案,小王也不会傻傻的拿着电话去等小李的答案吧,于是小王就对小李说,我还要去逛街,你知道了答案就打我电话告诉我,于是挂了电话,自己办自己的事情,过了一个小时,小李打了小王的电话,告诉他答案是2
异步回调。A:小王;B:小李。行动①:算出答案,A调用B执行;行动②:解决问题,B回调Asolve(String result)方法。
3.2 Android View的点击方法onclick()。onclick()是一个回调方法。同步回调。

  • 匿名内部类形式:匿名内部类必须实现一个接口或继承一个父类,但最多只能实现/继承一个
public class MainActivity extends Activity {  
    //不需要调用接口

    private Button button;  

    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        button =(Button)findViewById(R.id.button1);  

        /** 
         * 直接实现接口→相当于this引用 。即调用B的Bf方法,并且new相当于传入自身接口参数
         */  
        button.setOnClickListener(new View.OnClickListener() {
            /** 
             * 实现接口中的方法(回调函数)
             */  
            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
            }
        });
    }
}  
  • 内部类形式
public class MainActivity extends Activity {  
    //不需要调用接口

    private Button button;  

    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        button =(Button)findViewById(R.id.button1);  

        /** 
         * 相当于调用B的Bf方法,传入自身参数 
         */  
        button.setOnClickListener(new MyClickListener)
    }
    /** 
     * 内部类,实现接口 
     */  
    class MyClickListener implements View.OnClickListener{
        /** 
         * 实现接口中的方法(回调函数)
         */  
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
        }
    }
}  
  • 顶级类形式:类本身作为事件监听器
public class MainActivity extends Activity implements OnClickListener{  //调用接口

    private Button button;  

    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        button =(Button)findViewById(R.id.button1);  

        /**
         * 相当于调用B的Bf方法 
         * this(传入的参数):引用自身,相当于A
         */  
        button.setOnClickListener(this);  
    }  

    /** 
     * 用户点击Button时调用的回调函数,即实现接口里的方法
     */  
    @Override  
    public void onClick(View v) {  
        Toast.makeText(getApplication(), "OnClick", Toast.LENGTH_LONG).show();  
    }  
}  
  1. 2.

引用资料:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值