搞过Android的同志们,尤其是初学者,对于接口回调应该不陌生的,至少应该见过下面的代码:
//给按钮设置点击事件
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
OnClickListener就是android系统所预留好的接口,我们写的应用程序中传入回调对象,这样就可以达到接口统一,实现不同的效果。
什么是接口回调?
接口回调是用接口句柄来得到并调用实现这个接口的子类的引用。也可以理解为把实现接口的类的实例的引用赋值给接口变量后,该接口变量就可以回调类重写的接口方法。
听起来有点绕口,举个例子:
Code B想调用Code A中的A(),但是又想A()在执行的过程中调用Code B自身中的CallB(),那么可以定义一个接口IA,IA可以直接调callB(),CodeB实现IA接口,并且重写了里面的callB(),而Code A通过持有接口IA的引用ia,通过ia.callB()调用callB(),只需要Code B在调用Code A中的A()之前,传入实现接口IA的Code B引用。这个过程就是接口回调。
用代码描述这个过程:
IA可以直接调用callB()
public interface IA {
void callB();
}
CodeA通过持有IA接口的引用,直接调用callB()
public class CodeA {
private IA ia;
public void setIa(IA ia) {
this.ia = ia;
}
public void A() {
System.out.println("i am is A() of CodeA !");
ia.callB();
System.out.println("A() is finished !");
}
}
CodeB实现IA接口,重写callB()
public class CodeB implements IA{
//在调用CodeA.A()之前,传入实现IA接口的CodeB引用
public void doA() {
CodeA codeA = new CodeA();
codeA.setIa(this);
codeA.A();
}
@Override
public void callB() {
System.out.println("i am is callB() of CodeB !");
}
}
测试:
public class Main {
public static void main(String[] args) {
new CodeB().doA();
}
}
结果输出:
i am is A() of CodeA !
i am is callB() of CodeB !
A() is finished !
接口回调的好处
引用博客https://blog.csdn.net/bjyfb/article/details/10462555
为了使我们写的函数接近完美,就把一部分功能外包给别人,让别人个性化定制,至于别人怎么实现不管,我唯一要做的就是定义好相关接口,这一设计允许了底层代码调用高层定义的子程序,增强程序灵活性,和反射有着异曲同工之妙,这才是回调的真正原因!
上层模块封装时,很难预料下层模块会如何实现,因此,上层模块只需定义好自己需要但不能预料的接口(也就是回调接口),当下层模块调用上层模块时,根据当前需要的实现回调接口,并通过注册或参数方式传入上层模块即可,这样就实现下层调用上层,并且上层还能根据传入的引用来调用下层的具体实现,将程序的灵活性大大的增加了。