《Java2》接口回調(diào)
接口回調(diào)定義
- 接口和類一樣桦卒,是Java中的一種數(shù)據(jù)類型愉烙,用接口聲明的變量稱之為接口變量
- 接口變量中存儲(chǔ)的是實(shí)現(xiàn)了該接口的類的實(shí)例的引用
接口回調(diào)借用了C語言中指針回調(diào)的術(shù)語,
- 指針回調(diào),表示一個(gè)變量的地址在某一時(shí)刻存放在一個(gè) 指針變量 中,這個(gè) 指針變量 可以間接操作該變量中存放的數(shù)據(jù);
- 接口回調(diào)绩郎,指的是可以把實(shí)現(xiàn)某一接口的類創(chuàng)建的對(duì)象的引用賦值給該接口聲明的 接口變量,那么該 接口變量 就可以調(diào)用被類實(shí)現(xiàn)的接口方法翁逞。(其實(shí)當(dāng) 接口變量 在調(diào)用被類實(shí)現(xiàn)的接口方法時(shí)肋杖,就是在通知相應(yīng)的對(duì)象調(diào)用這個(gè)方法)
但是接口變量無法調(diào)用類中其他的非接口方法;
(類似于上轉(zhuǎn)型對(duì)象調(diào)用子類重寫的方法)
例如:Com為接口挖函,ImpleCom為實(shí)現(xiàn)了該接口的一個(gè)類状植;
Com com
:此時(shí)com為一個(gè)空接口;
ImpleCom object = new ImpleCom()
:創(chuàng)建一個(gè)實(shí)現(xiàn)Com接口的對(duì)象object怨喘;
com = object
:此時(shí)com能夠操縱object實(shí)現(xiàn)的接口的方法津畸;
接口回調(diào)與多態(tài)
把實(shí)現(xiàn)接口的類的實(shí)例的引用賦值給接口變量后,該接口變量就可以回調(diào)類重寫的接口方法必怜。
不同的類在實(shí)現(xiàn)同一個(gè)接口時(shí)可能具有不同的實(shí)現(xiàn)方式肉拓,那么接口變量就在回調(diào)接口方法時(shí)可能具有多種形態(tài)。
接口參數(shù)
如果一個(gè)方法的參數(shù)為接口類型的數(shù)據(jù)梳庆,那么可以將任何實(shí)現(xiàn)該接口的類的實(shí)例的引用傳遞給該參數(shù)暖途,接口參數(shù)也可以回調(diào)類實(shí)現(xiàn)的方法
接口回調(diào)
所謂的回調(diào),不過就是接口使用匿名內(nèi)部類而已膏执。
我理解的回調(diào)驻售,就是:
- 定義接口;
- 定義方法胧后,方法參數(shù)為接口芋浮,方法中調(diào)用接口抱环;
- 調(diào)用該方法壳快,傳入的一個(gè)接口實(shí)現(xiàn)類;
不要看網(wǎng)上那什么亂七八糟小明小紅什么吃飯的例子镇草,亂死了
其實(shí)最常見的是在接口中傳入匿名內(nèi)部類眶痰;
在計(jì)算機(jī)程序設(shè)計(jì)中,回調(diào)函數(shù)梯啤,或簡(jiǎn)稱回調(diào)竖伯,是指通過函數(shù)參數(shù)傳遞到其它代碼的,某一塊可執(zhí)行代碼的引用。
這一設(shè)計(jì)允許了底層代碼調(diào)用在高層定義的子程序七婴。
在Java里面使用接口來實(shí)現(xiàn)回調(diào)祟偷。
所謂的回調(diào),就是程序員A寫了一段程序(程序a)打厘,其中預(yù)留有回調(diào)函數(shù)接口修肠,并封裝好了該程序。
程序員B要讓a調(diào)用自己的程序b中的一個(gè)方法户盯,于是他通過a中的接口回調(diào)自己b中的方法嵌施。
1)首先定義一個(gè)類Caller,按照上面的定義就是程序員A寫的程序a莽鸭,這個(gè)類里面保存一個(gè)接口引用吗伤。
public class Caller {
//保存一個(gè)接口引用
private MyCallInterface callInterface;
public Caller() {
}
public void setCallFunc(MyCallInterface callInterface) {
this.callInterface = callInterface;
}
public void call() {
callInterface.printName();
}
}
2)當(dāng)然需要接口的定義,為了方便程序員B根據(jù)我的定義編寫程序?qū)崿F(xiàn)接口硫眨。
public interface MyCallInterface {
public void printName();
}
3)第三是定義程序員B寫的程序b實(shí)現(xiàn)接口足淆。
public class Client implements MyCallInterface {
@Override
public void printName() {
System.out.println("This is the client printName method");
}
}
4)測(cè)試如下
public class Test {
public static void main(String[] args) {
Caller caller = new Caller();
caller.setCallFunc(new Client());
caller.call();
}
}
5)也可以在測(cè)試方法中直接使用匿名類,省去第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();
}
}
到這里應(yīng)該明白了吧缸浦,
這不就是接口作為參數(shù)
可以將接口類型的參數(shù)作為方法參數(shù),在實(shí)際是使用時(shí)可以將實(shí)現(xiàn)了接口的類傳遞給方法氮兵,后方法或按照重寫的原則執(zhí)行裂逐,
實(shí)際調(diào)用的是實(shí)現(xiàn)類中的方法代碼體,這樣便根據(jù)傳進(jìn)入的參數(shù)的不同而實(shí)現(xiàn)不同的功能泣栈。
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);
}
}
比較多見的是在接口上使用匿名內(nèi)部類卜高。
btn_activity.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
i1 = new Intent(MainActivity.this,Main2Activity.class);
startActivity(i1);
}
)};
我之所以會(huì)想到這個(gè)問題,是因?yàn)榭吹紽ragment與Activity使用接口回調(diào)通信南片,
在Fragment中定義一個(gè)內(nèi)部回調(diào)接口,再讓包含該Fragment的Activity實(shí)現(xiàn)該回調(diào)接口掺涛,F(xiàn)ragment就可以通過回調(diào)接口傳數(shù)據(jù)了。
- 在Fragment中定義一個(gè)接口,接口中定義抽象方法,傳什么類型的數(shù)據(jù)參數(shù)就設(shè)置為什么類型;
/*接口*/
public interface CallBack{
/*定義一個(gè)獲取信息的方法*/
public void getResult(String result);
}
- 在Fragment中接著還有寫一個(gè)調(diào)用接口中的抽象方法,把要傳遞的數(shù)據(jù)傳過去疼进;
(msg的獲取不要弄錯(cuò)位置了薪缆,容易空指針異常)
/*接口回調(diào)*/
public void getData(CallBack callBack){
String msg = medit.getText().toString();
callBack.getResult(msg);
}
- 在Activity中適當(dāng)時(shí)機(jī)使用接口,重寫抽象方法獲取數(shù)據(jù)伞广;
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
//使用接口回調(diào)獲取數(shù)據(jù)
public void getResult(String result) { /*打印信息*/
Toast.makeText(MainActivity.this, result, Toast.LENGTH_LONG).show();
}
});
}
});
在這里拣帽,點(diǎn)擊事件中調(diào)用Fragment.getData()方法,傳入的參數(shù)是一個(gè)實(shí)現(xiàn)了接口的匿名內(nèi)部類(該內(nèi)部類重寫了getResult()方法)嚼锄,在運(yùn)行g(shù)etData()方法時(shí)减拭,獲取到當(dāng)前對(duì)象中的msg變量,將msg作為參數(shù)傳入callBack.getResult(msg)方法区丑,在Activity界面中得到了Fragment中的信息拧粪,所以實(shí)現(xiàn)了類間的數(shù)據(jù)傳遞修陡。
這也可以說明,傳入的接口不同可霎,獲得不同的實(shí)現(xiàn)魄鸦。