回调机制小结

一、简介

所谓回调:就是A类中调用B类中的某个方法C,然后B类中反过来调用A类中的方法D,D这个方法就叫回调方法。

举个生活中的例子:我打电话向你请教问题,是个难题,你一时想不出解决方法,于是我们约定:等你想出办法后打手机通知我,我就挂掉电话办其它事情去了。过了一段时间,你打过来告诉我答案。

在这里插入图片描述
C在调用a后是不会自己调用b的,C提供b的目的就是让S来调用。但是S并不知道C提供的b是什么,因此需要约定统一的接口规范。

总结一下:

  • Class A实现接口CallBack callback——背景1
  • class A中包含一个class B的引用b ——背景2
  • class B有一个参数为callback的方法f(CallBack callback) ——背景3
  • A的对象a调用B的方法 f(CallBack callback) ——A类调用B类的某个方法C
  • 然后b就可以在f(CallBack callback)方法中调用A的方法 ——B类调用A类的某个方法D

上文举的生活中的例子中:你后来打手机告诉我结果就是一个回调过程,我的手机号码有效并且手机能够接收到你的呼叫,这是回调函数必须符合接口规范。


二、详述

安卓中很多地方都用到了回调机制:

场景一:
Android View的点击方法onclick()方法

Button button = (Button)this.findViewById(R.id.button);  
button.setOnClickListener(newButton.OnClickListener() {  
   //回调函数  
   @override  
   public void onClick(View v) {  
      buttonTextView.setText("按钮被点击了");  
   }  
});  
//这个是View的一个回调接口
/**
 * Interface definition for a callback to be invoked when a view is clicked.
 */
public interface OnClickListener {
    /**
     * Called when a view has been clicked.
     *
     * @param v The view that was clicked.
     */
    void onClick(View v);
/**
 * View类,就相当于B类,贴出关键代码
 *
 */
public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {
	/**
     * Listener used to dispatch click events.
     * This field should be made private, so it is hidden from the SDK.
     * {@hide}
     */
    protected OnClickListener mOnClickListener;
    
    /**
     * setOnClickListener()的参数是OnClickListener接口------>背景三
     * Register a callback to be invoked when this view is clicked. If this view is not
     * clickable, it becomes clickable.
     *
     * @param l The callback that will run
     *
     * @see #setClickable(boolean)
     */
    
    public void setOnClickListener(OnClickListener l) {
        if (!isClickable()) {
            setClickable(true);
        }
        mOnClickListener = l;
    }
    
    
    /**
     * Call this view's OnClickListener, if it is defined.
     *
     * @return True there was an assigned OnClickListener that was called, false
     *         otherwise is returned.
     */
    public boolean performClick() {
        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
 
        if (mOnClickListener != null) {
            playSoundEffect(SoundEffectConstants.CLICK);
            
            //这个不就是相当于B类调用A类的某个方法D,这个D就是所谓的回调方法咯
            mOnClickListener.onClick(this);
            return true;
        }
 
        return false;
    }
}

场景一:
Activity的整个生命周期基本上都说回调函数在发挥作用

@Override  
public void onCreate(BundlesaveInstanceState) {  
   super.onCreate(saveInstanceState);  
   // You code...  
}  
@Override  
public void onResume() {  
   super.onResume();  
   // You code...  
}  

下面再模拟打电话例子的代码:


/**
 * 回调接口(规范)
 */
public interface CallBack {
	/**
	 * 这个是小李知道答案时要调用的函数告诉小王,也就是回调函数
	 * @param result 是答案
	 */
	public void solve(String result);
}
/**
 * 相当于服务端S class B
 *
 * @author ReaganZhu
 * @email 2668526325@qq.com
 * @date 2020/8/17 10:39
 */
public class You implements Runnable {

    private String who;
    private CallBack callBack;

    //class B有一个参数为callback的方法f(CallBack callback) ——背景3
    public void setCallBack(String who,String question,CallBack callBack) {
        this.who = who;
        System.out.println("你说:当前联系到我的人是"+who+",问题是"+question);
        this.callBack =callBack;
    }

    public void handleThings(){
        //假如你现在正在想问题的答案,需要一点时间
        for(int i=0;i<100000;i++){
            if(i == 0){
                System.out.println("你正在思考问题.....");
            }
        }

        String answer = "答案是A";
        //想到问题的办法了
        System.out.println("你说:想到答案了,准备打回去给"+who+"告诉他答案");
        //b就可以在f(CallBack callback)方法中调用A的方法 ——B类调用A类的某个方法D
        callBack.callBackByTel(answer);
    }

    @Override
    public void run() {
        try {
            Thread.sleep(1000);
            handleThings();
        } catch (Exception e) {
            e.printStackTrace();

        }
    }
}
/**
 * 相当于客户端C class A
 *
 * @author ReaganZhu
 * @email 2668526325@qq.com
 * @date 2020/8/17 22:48
 */
public class Me {
    public static void main(String[] args){
        Me me = new Me();
        //A的对象a调用B的方法 f(CallBack callback) ——A类调用B类的某个方法 C
        me.hasQuestion();
    }

    private void hasQuestion(){
        //现在有问题想不出来答案,想去问你
        //class A中包含一个class B的引用b ——背景2
        You you = new You();
        //Class A实现接口CallBack callback——背景1
        you.setCallBack("蜗牛", "某道题答案是什么?", new CallBack() {

            @Override
            public void callBackByTel(String answer) {
                System.out.println("我说:嗯,好的,我收到答案了:"+answer+",谢谢");
            }
        });
        //你接到电话,起床开始思考问题
        new Thread(you).start();
    }

}

//运行结果:
你说:当前联系到我的人是蜗牛,问题是某道题答案是什么?
你正在思考问题…
你说:想到答案了,准备打回去给蜗牛告诉他答案
我说:嗯,好的,我收到答案了:答案是A,谢谢

其实线程run()也是一个回调方法,当执行Thread的start()方法就会回调这个run()方法,还有处理消息都比较经典等等


三、小结

程序的本质就是代码跳转,不管同步异步反射接口虚函数,本质上都是函数调用。函数我们要调用它,就需要它的指针,不同语言通过不同的方式来得到这个指针。而我们定义的接口其实就是一个函数指针,那么那个注册过程,其实就是相当于对那个函数指针赋值。通过这个函数指针来调用我们定义的自实现函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值