java 自定义函数的调用_Java/Android中的函数调用回调函数自定义回调函数
在做Android自定義控件時遇到要自定義回調函數的問題,想想自己還暫時沒有那么精深的技術,趕緊返過頭回來再重新研究Java中回調函數的問題。然而不幸的是,網上太多雜亂的帖子和博客都是轉來轉去,而且都是那一篇“C中的回調函數.....指針.....java....”,一點看不出來是自己的思路,估計都是哪哪哪抄來的!(呵呵,要么就是吐槽對了,要么就是我水平太爛讀不懂還妄加評論
)還有一些很不錯的文章,我會在最后參考中加上鏈接,大家可以看看。
那么來開始我們的正題——什么是回調函數?
我們一步步深入,先從函數調用開始:
什么是函數(方法)調用?
(別的什么語言的都忘了……呵呵,只看Java)Java中的函數調用無非就是(1)一個類中方法為了完成一個業務在執行過程中調用另一個方法,另一個方法也可以是自己,那就是遞歸啦;(2)不同類之間的函數調用,比如Class B(調用者Caller)中要調用Class A對象的一個方法(被調用者Callee)(不管A是作為B的成員,還是作為函數參數傳進來)。方法調用是我們編程中必不可少的,可能我們平時視而不見罷了,否則一個工程的不同CLASS怎么協同工作呢?雖然簡單,還是畫個圖說一下吧,待會對比一下可以更好的解釋回調的機制:
如上圖Class B的函數method_B在執行過程中要調用成員a(Class A)的method_A1方法。
我們剛開始學的時候都是這樣做的。但是這樣做存在問題,讓我們來回顧一下我們當年學習的經過,不斷將這個問題解釋清楚:舉個例子吧,不然嘴笨表達不清楚——A類是鳥類,B就是我們的工具類,現在我們要在工具類中完成這樣的需求:通過工具類中的方法method_B完成不同鳥類飛的正確動作。
第一階段:顯然就兩個類完成不了這個需求!接著我們學習了繼承,我們創建了“麻雀”、“大雁”、“鴕鳥”……各種“鳥”類子類,通過不同子類來完成不同的飛法,然后在工具類中創建不同子類的對象賦值給a,這樣需求完成了。但是回頭看看,我們創建了一大堆的子類,而且還用了隱式類型轉換(子類賦值給父類),顯然不夠滿意;
第二階段:后來,我們又學習了重載函數,在鳥類中創建一系列同名同名的“飛”函數,傳入參數類型分別為麻雀、大雁……,這樣我們就不用隱式轉換了,直接調用鳥類對象a的飛方法,傳入不同的大雁、麻雀……,a就能正確的飛了。這樣需求也完成了,雖然避免了使用隱式轉換,但是那些為數眾多的子類可一個也沒有落下。這樣做顯然也不符合我們的期望(我們的期望是什么?就是干最少的活,鳥就能正確的飛)。
以上實現方式的問題就顯而易見了:一方面我們要維護那些眾多的子類,增加很大的工作量;另一方面,這樣的編碼缺乏靈活性,有多少種鳥你知道嗎,每種鳥又是怎么飛的你知道嗎,如果幾種鳥極為相似,你是創建不同的類呢還是歸為一類?所以有了下邊這種實現方式,就是采用“回調函數”——
什么是回調函數?
直接上圖吧:
如上圖,回調函數中必然用到接口。下邊是感覺寫得好的一段理解:
在android的學習過程中經常會聽到或者見到“回調”這個詞,那么什么是回調呢?所謂的回調函數就是:在A類中定義了一個方法,這個方法中用到了一個接口和該接口中的抽象方法,但是抽象方法沒有具體的實現,需要B類去實現,B類實現該方法后,它本身不會去調用該方法,而是傳遞給A類,供A類去調用,這種機制就稱為回調。
我認為,上圖中B類的方法method_B在調用a對象的method_A1時,method_A1執行到interface的抽象方法不知道怎么實現,正好B在調用他的時候提供了具體實現,所以method_A1返回來調用method_B提供的實現,這就是回調。其實,回調函數就是在一個不確定實現的方法METHOD中用interface或者它的抽象方法留個口子,留給具體調用者(調用前邊那個不確定的方法METHOD)在調用時提供具體實現來補上那個口子。從而達到更靈活地編碼的目的,也大大減少了子類的使用。就拿上邊沒完的例子繼續吧——
我們這樣來實現:先定義一個接口,接口中聲明抽象方法“飛”;在“鳥”類的“起飛”方法中把接口對象作為一個參數傳進來,剩下的該怎么做就怎么做,遇到要飛的地方不知道具體怎么飛就調用接口提供的抽象方法“飛”;在工具類中調用“鳥”類的“起飛”方法時要實現了抽象方法的對象作為參數傳入,然后你想讓它怎么飛就怎么飛,具體實現是你調用的時候現寫的。怎么樣,這樣的實現好吧?不用隱式轉換,不用大量子類,調用的時候遇到什么鳥就怎么飛,達到了我們少干活的目的!
什么是自定義回調函數?
自定義回調函數,顧名思義,就是我們自己定義的回調函數。其實上邊那個例子就是自定義回調函數!我們習慣上把別人定義好的回調函數叫作回調函數,Android系統中TextView、ImageView等和它們的子類控件的Onclick事件響應就是典型的回調機制。關于這個這位大蝦講得比我好——詳細介紹Android中回調函數機制,詳細看看會很有幫助的!
一個簡單的自定義回調函數的例子
最后在舉個簡單的有代碼的例子,看一下回調函數的運行過程:
首先,我們定義一個interface:
public?interface?MyInterface?{
void?sayYourName();
}
接著,我們定義一個類,其中一個方法以接口MyInterface類型的對象作為參數:
public?class?MyClass?{
public?MyClass()?{
Log.e("WangJ",?"MyClass-constructor");?????????//標注構造函數
}
/*?用接口類型的對象作為輸入參數?*/
public?void?sayYourName(MyInterface?myInterface){
Log.e("WangJ",?"MyClass-sayYourName_start");????//標注方法開始
myInterface.sayYourName();??????????????????????//遇到不知道具體實現的時候就用接口的抽象方法
Log.e("WangJ",?"MyClass-sayYourName_finish");???//方法結束
}
}
最后,我們在Activity中調用這個類,創建對象并調用其方法,期間實現接口中抽象方法的具體實現邏輯,供回調使用:
public?class?MainActivity?extends?Activity?{
@Override
protected?void?onCreate(Bundle?savedInstanceState)?{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyClass?myClass?=?new?MyClass();
myClass.sayYourName(new?MyInterface()?{?????????????????????//實現接口并作為參數傳入
@Override
public?void?sayYourName()?{
Log.e("WangJ",?"callBack-interface-implementor");????//具體操作實現
}
});
}
}
好了,運行一下(我們這個例子沒有任何界面,即默認Activity的界面,看日志):
運行的順序就是我們之前理解的:在B中調用A中的方法,A中方法在運行到接口中抽象方法時返回B中尋找具體實現(這就是回調),回調完成后繼續執行下邊未完成的步驟。
好了,以上就是我所認識的回調函數,聽起來高深,在你弄懂以后發現也沒有太大的難度。但是想想Java研發者在設計這種機制的時候是多么有遠見啊(好崇拜,雖然不知道他是誰)!文筆有限,理解不夠,如有不足或錯誤,歡迎指正!最后如約附上那幾篇不錯的文章——
總結
以上是生活随笔為你收集整理的java 自定义函数的调用_Java/Android中的函数调用回调函数自定义回调函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 安卓 html_java –
- 下一篇: java反射 初始化bean_通用jav