《Java2》接口回调
接口回调定义
- 接口和类一样,是Java中的一种数据类型,用接口声明的变量称之为接口变量
- 接口变量中存储的是实现了该接口的类的实例的引用
接口回调借用了C语言中指针回调的术语,
- 指针回调,表示一个变量的地址在某一时刻存放在一个 指针变量 中,这个 指针变量 可以间接操作该变量中存放的数据;
- 接口回调,指的是可以把实现某一接口的类创建的对象的引用赋值给该接口声明的 接口变量,那么该 接口变量 就可以调用被类实现的接口方法。(其实当 接口变量 在调用被类实现的接口方法时,就是在通知相应的对象调用这个方法)
但是接口变量无法调用类中其他的非接口方法;
(类似于上转型对象调用子类重写的方法)
例如:Com为接口,ImpleCom为实现了该接口的一个类;
Com com
:此时com为一个空接口;
ImpleCom object = new ImpleCom()
:创建一个实现Com接口的对象object;
com = object
:此时com能够操纵object实现的接口的方法;
接口回调与多态
把实现接口的类的实例的引用赋值给接口变量后,该接口变量就可以回调类重写的接口方法。
不同的类在实现同一个接口时可能具有不同的实现方式,那么接口变量就在回调接口方法时可能具有多种形态。
接口参数
如果一个方法的参数为接口类型的数据,那么可以将任何实现该接口的类的实例的引用传递给该参数,接口参数也可以回调类实现的方法
接口回调
所谓的回调,不过就是接口使用匿名内部类而已。
我理解的回调,就是:
- 定义接口;
- 定义方法,方法参数为接口,方法中调用接口;
- 调用该方法,传入的一个接口实现类;
不要看网上那什么乱七八糟小明小红什么吃饭的例子,乱死了
其实最常见的是在接口中传入匿名内部类;
在计算机程序设计中,回调函数,或简称回调,是指通过函数参数传递到其它代码的,某一块可执行代码的引用。
这一设计允许了底层代码调用在高层定义的子程序。
在Java里面使用接口来实现回调。
所谓的回调,就是程序员A写了一段程序(程序a),其中预留有回调函数接口,并封装好了该程序。
程序员B要让a调用自己的程序b中的一个方法,于是他通过a中的接口回调自己b中的方法。
1)首先定义一个类Caller,按照上面的定义就是程序员A写的程序a,这个类里面保存一个接口引用。
public class Caller {
//保存一个接口引用
private MyCallInterface callInterface;
public Caller() {
}
public void setCallFunc(MyCallInterface callInterface) {
this.callInterface = callInterface;
}
public void call() {
callInterface.printName();
}
}
2)当然需要接口的定义,为了方便程序员B根据我的定义编写程序实现接口。
public interface MyCallInterface {
public void printName();
}
3)第三是定义程序员B写的程序b实现接口。
public class Client implements MyCallInterface {
@Override
public void printName() {
System.out.println("This is the client printName method");
}
}
4)测试如下
public class Test {
public static void main(String[] args) {
Caller caller = new Caller();
caller.setCallFunc(new Client());
caller.call();
}
}
5)也可以在测试方法中直接使用匿名类,省去第3步。
public class Test {
public static void main(String[] args) {
Caller caller = new Caller();
//caller.setCallFunc(new Client());使用匿名类代替
caller.setCallFunc(new MyCallInterface() {
public void printName() {
System.out.println("This is the client printName method");
}
});
caller.call();
}
}
到这里应该明白了吧,
这不就是接口作为参数
可以将接口类型的参数作为方法参数,在实际是使用时可以将实现了接口的类传递给方法,后方法或按照重写的原则执行,
实际调用的是实现类中的方法代码体,这样便根据传进入的参数的不同而实现不同的功能。
interface Extendbroadable ...{
public void inPut();
}
class KeyBroad implements Extendbroadable ...{
public void inPut() ...{
System.out.println(" hi,keybroad has be input into then mainbroad! ");
}
}
class NetCardBroad implements Extendbroadable ...{
public void inPut() ...{
System.out.println(" hi,netCardBroad has be input into then mainbroad! ");
}
}
class CheckBroad ...{
public void getMainMessage(Extendbroadable ext)...{
ext.inPut();
}
}
public class InterfaceTest01 ...{
public static void main(String []args) ...{
KeyBroad kb=new KeyBroad();
NetCardBroad ncb=new NetCardBroad();
CheckBroad cb=new CheckBroad();
cb.getMainMessage(kb);
cb.getMainMessage(ncb);
}
}
比较多见的是在接口上使用匿名内部类。
btn_activity.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
i1 = new Intent(MainActivity.this,Main2Activity.class);
startActivity(i1);
}
)};
我之所以会想到这个问题,是因为看到Fragment与Activity使用接口回调通信,
在Fragment中定义一个内部回调接口,再让包含该Fragment的Activity实现该回调接口,Fragment就可以通过回调接口传数据了。
- 在Fragment中定义一个接口,接口中定义抽象方法,传什么类型的数据参数就设置为什么类型;
/*接口*/
public interface CallBack{
/*定义一个获取信息的方法*/
public void getResult(String result);
}
- 在Fragment中接着还有写一个调用接口中的抽象方法,把要传递的数据传过去;
(msg的获取不要弄错位置了,容易空指针异常)
/*接口回调*/
public void getData(CallBack callBack){
String msg = medit.getText().toString();
callBack.getResult(msg);
}
- 在Activity中适当时机使用接口,重写抽象方法获取数据;
final MyFragment f1 = new MyFragment();
getSupportFragmentManager().beginTransaction().add(R.id.mylayout, f1).commit();
button = (Button) findViewById(R.id.btn);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
f1.getData(new MyFragment.CallBack() {
@Override
//使用接口回调获取数据
public void getResult(String result) { /*打印信息*/
Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();
}
});
}
});
在这里,点击事件中调用Fragment.getData()方法,传入的参数是一个实现了接口的匿名内部类(该内部类重写了getResult()方法),在运行getData()方法时,获取到当前对象中的msg变量,将msg作为参数传入callBack.getResult(msg)方法,在Activity界面中得到了Fragment中的信息,所以实现了类间的数据传递。
这也可以说明,传入的接口不同,获得不同的实现。