什么是回调函数
考虑两个类以及一个接口:A类和B类以及A类所实现的接口。
A类
package com.company.callbacktest;
public class AClass implements Callback{
@Override
public void caller() {
System.out.println("第三步:该函数是回调函数,即A的函数在B中被调用");
}
// A委托B做某事
public void aUseB(BClass bClass) {
bClass.process(this);
}
public static void main(String[] args) {
AClass classA = new AClass();
BClass bClass = new BClass();
System.out.println("第一步:A先委托B做某事");
classA.aUseB(bClass);
}
}
B类
package com.company.callbacktest;
public class BClass {
//为方便B进行调用(回调/通知)A, B需要进行持有A的引用
public void process(AClass classA) {
System.out.println("第二步:B类负责处理一些耗时的任务");
//B处理完事情之后进行回调(通知)A
classA.caller();
}
}
回调接口
package com.company.callbacktest;
public interface Callback {
public void caller();
}
回调的例子
子线程执行
此处的thread相当于上文叙述的B类,Runnable相当与上文的接口,当B类执行自己的start方法的内部时就回回调接口的run方法。此处的匿名内部类就相当于上文的A类,只是没有体现出来。
public class Test {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("线程执行");
}
});
thread.start();
}
}
android的点击事件
Button相当于上文的B类,View.OnClickListener是接口,只有一个onClick()函数,类似上面的caller函数,只是此处用匿名内部类实现了这个接口。java虚拟机监听着按钮,只要按钮被点击,onClick()就会被调用,而上面的例子是我们在A类的main函数代码中(只是相当于一个主线程,B类方法的调用在哪被调用无关紧要)调用的,此处通常是在activity中被调用。
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//点击后的具体实现
}
});
参考
总结
我对回调的理解就是:A类对象自己有一段代码不能立即执行,需要等到某一个时间点才可以执行,但是这个时机点可能得B类对象来决定,既然如此A类对象的这部分待执行的代码可以自己封装成一段代码,然后在B类对象的某个方法中的合适时机来调用A类的这个封装函数,那么A类的这个待执行的封装函数就被称为回调函数(感觉好像A在合适时机执行了自己想要执行的代码,但是实际上却不是在自己的上下文环境中执行的,而是在B的上下文环境中执行的)。希望能结合多个场景进行加深印象,回调的本质就是一种异步场景下的函数调用,以长期过程性的思维模式去理解异步编程确实有点别扭。