(Android)接口回调
1、什么是接口回调
那么何为接口回调呢?
接口回调是指:
可以把使用实现了某一接口的类创建的对象的引用,赋给该接口声明的接口变量,那么该接口变量就可以调用被类实现的接口的方法。实际上,当接口变量调用被类实现的接口中的方法时,就是通知相应的对象调用接口的方法,这一过程称为对象功能的接口回调。
接口回调说白了就是通过接口来调用接口里面的方法
2、接口回调的作用
最主要的作用便是解耦
- 削弱模块间的协作性,也就是耦合性,使得模块之间高度独立,模块间更多的从事着单向的调用工作。一个模块需要某种服务就去找另一个模块,这使得程序呈现出层次性,高层通过接口调用底层,底层提供服务。摈弃模块间你中有我我中有你的暧昧关系。
模块间的相互协作
- 但我们又需要模块间的协作,所以需要回调(C++中是指针)。如果A对象关心B对象的状态变化,那么给B对象的状态的变化注册接口回调函数,A实现接口,让接口函数通知A,B对象状态的改变,这样在封装了模块变化的同时实现了模块间的协作关系,另辟独径的给对象解耦。
函数的参数
- 回调函数跟普通函数只是在调用函数时略有区别。一般调用普通函数时,直接写函数名即可。但是在调用所谓“回调”函数时,是把它作为参数传递给另一函数。关键就在于“参数”这两个字。为什么要把某个东西参数化?就是它存在变化的可能性。既然可以把变量做成参数,那么函数也同样可以做成参数,只要它们有变化的可能。对于一成不变的东西,显然直接嵌入便可。
3、Java中的引用
- 如果a是类A的一个引用,那么a可以指向类A的一个实例。或者说指向类A的一个子类,这是向上转型的情形。
- 如果a是接口 A 的一个引用,那么a必须指向实现了接口A的一个类的实例。这是接口回调的情形。
为了直观我就直接上代码,如下:
interface Animal{
void eat();
}
class dog implements Animal{
public void eat(){
System.out.println("狗吃肉");
}
}
class cat implements Animal{
public void eat(){
System.out.println("猫吃老鼠");
}
}
public class Example{
public static void main(String args[]){
Animal a; //声明接口变量
a=new dog(); //实例化,接口变量中存放对象的引用
a.eat(); //接口回调,具体如何运行有实现类重写抽象方法
a=new cat(); //实例化,接口变量中存放对象的引用
a.eat(); //接口回调
}
}
结果为:
狗 吃 肉
猫 吃 老 鼠
- 咋一看可能会有人说这不就是多态的用法吗?没错,实际上与多态并无太大的区别(建议顺便复习一下多态方面的知识)。
4、案例分析
比较经典的案例为OnClickListener点击事件,因比较常见在这里就不做赘述。本案例比较简单主要功能为:从Fragment中利用接口回调的方式向Activity中传递数据,具体代码如下:
Fragment类public class EditFragment extends Fragment { private EditText et; private Button but; //1. 创建一个接口以及抽象方法 public interface TextCallback { //将想要传递出去的数据作为抽象方法的参数列表 void getText (String str); } //2. 定义一个接口类型的变量,并给该变量进行初始化操作 private TextCallback callback; public void setCallback(TextCallback callback) { this.callback = callback; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // TODO Auto-generated method stub return inflater.inflate(R.layout.myfrag, container,false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { // TODO Auto-generated method stub super.onViewCreated(view, savedInstanceState); initView(view); but.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub String str = et.getText().toString(); /* 通过接口回调的方式 //3. 通过接口对象调用抽象方法 callback.getText(str); } }); } }
在 EditFragment中有一个EditText和一个Button在EditText中输入内容点击按钮输入的内容便会显示在MainActivity中的TextView上,从而实现从EditFragment向MainActivity中传递数据。当通过接口对象调用抽象方法即:callback.getText(str);时具体实现是方法为MainActivity中重写的getText方法。
MainActivity类
public class MainActivity extends Activity {
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView)findViewById(R.id.textView1);
EditFragment ef = new EditFragment();
//给接口赋值,
ef.setCallback(new TextCallback() {
//当在Fragment中通过接口对象调用抽象方法时运行以下方法
@Override
public void getText(String str) {
// TODO Auto-generated method stub
tv.setText(str);
}
});
//将EditFragment添加到屏幕上显示
getFragmentManager().beginTransaction().replace(R.id.frame, ef ).commit();
}
}