寫安卓這麼久了,對于回調一直沒有深入研究。其實所謂的回調函數就是:在A類中定義了一個方法,這個方法中用到了一個接口和該接口中的抽象方法,但是抽象方法沒有具體的實作,需要B類去實作,B類實作該方法後,它本身不會去調用該方法,而是傳遞給A類,供A類去調用,這種機制就稱為回調。(參考系統的view的onClick()接口了解)
我的了解:老公要老婆做菜,老婆不知道老公想吃什麼菜,那麼就在老婆做菜的方法裡傳入一個做菜的接口,調用一個沒實作的抽象方法,當老公讓老婆做菜時調用做菜的方法,然後實作做菜接口,老婆的做菜方法裡具體實作那個抽象方法,就可以想做什麼菜接寫什麼代碼啦,這樣就做到了調用者想幹什麼自己實作的思想了。
其實網文一大推都在說,也不過是互相轉載而已,這其中看到幾篇比較不錯的,這裡轉載一下。
1-----版權聲明:^_^ 尊重原創,共享知識,轉載請注明"_程式猿大人_"http://blog.csdn.net/a_running_wolf
什麼是自定義回調函數?
自定義回調函數,顧名思義,就是我們自己定義的回調函數。其實上邊那個例子就是自定義回調函數!我們習慣上把别人定義好的回調函數叫作回調函數,Android系統中TextView、ImageView等和它們的子類控件的Onclick事件響應就是典型的回調機制。關于這個這位大蝦講得比我好——詳細介紹Android中回調函數機制,詳細看看會很有幫助的!
一個簡單的自定義回調函數的例子
最後在舉個簡單的有代碼的例子,看一下回調函數的運作過程:
首先,我們定義一個interface:
[java] view plain copy
- public interface MyInterface {
- void sayYourName();
- }
接着,我們定義一個類,其中一個方法以接口MyInterface類型的對象作為參數:
[java] view plain copy
- 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中調用這個類,建立對象并調用其方法,期間實作接口中抽象方法的具體實作邏輯,供回調使用:
[java] view plain copy
- 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中尋找具體實作(這就是回調),回調完成後繼續執行下邊未完成的步驟。
2----參考http://blog.csdn.net/liushuaikobe/article/details/7934565
用Java寫了這麼久的程式,一直沒有了解什麼是回調,在最近的Android開發工作中,一個偶然的需求讓我突然就對Java中的回調有了一個了解,遂記錄之。
首先這個需求是這樣的,一個Activity中的有一個View,我需要在不同的觸發條件下更換這個View的Layout,我們很容易想到寫一個方法,把要更換成的Layout的id傳進去,然後為這個View設定一下content。就可以在不同的條件下調用這個函數來設定View的layout了,這不難了解。
但是,假設,現在該View的Layout更換成了LayoutA,LayoutA裡面有一個ImageView,我要對該ImageView通過代碼設定一些屬性;然後,另一時刻,該View的Layout換成了LayoutB,LayoutB裡面有一個Button,我要對該Button通過代碼做一些設定,怎麼辦?
我們可以這樣解決:
[java] view plain copy
- class MyActivity extends Activity {
- View view;
- int currentContentFlag;
- private static final int ViewA = 1; // 标志着目前View顯示的内容是ViewA
- private static final int ViewB = 2; // 标志着目前View顯示的内容是ViewB
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- // 一些例如對view初始化工作略去
- // 我們在這裡設定View的layout的Id為layoutId_A
- currentContentFlag = ViewA; // 修改目前顯示内容的flag,告訴這個setViewContent函數裡面到底執行setViewA還是setViewB
- setViewContent(R.layout.layoutId_A);
- }
- private void setViewContent(int layoutId) {
- view = LayoutInflater.from(this).inflate(layoutId, null); // 設定View的内容
- switch (currentContentFlag) {
- case ViewA:
- // 說明目前View的内容是ViewA,在這裡用代碼對ViewA裡面的東西進行具體設定
- setViewA(view);
- break;
- case ViewB:
- // 說明目前View的内容是ViewB,在這裡用代碼對ViewB裡面的東西進行具體設定
- setViewB(view);
- break;
- default :
- break;
- }
- }
- private setViewA(View view) {
- }
- private setViewB(View view) {
- }
- }
這樣的話,每設定一次View的内容,都要修改目前顯示内容的flag,通過維護這個flag變量,來告訴這個setViewContent函數裡面到底執行setViewA還是setViewB。
這樣做可不可行呢?實作肯定也可以實作,但是,我想到了用回調機制來完成這件事。
什麼是回調呢?回調回調,回去調用。我了解回調,就是,在代碼執行的過程中,函數FunA()某一時刻被調用,那麼将轉去執行FunA(),在FunA執行的時候呢,又反過來去執行原代碼裡的一些東西。這應該是最淺顯的解釋了吧。
在Java語言裡面,我們可以通過interface實作自己的回調,Java裡面的interface真的太有用了。則上面的代碼可以改為下面的實作:
[java] view plain copy
- class MyActivity extends Activity {
- View view;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- // 一些例如對view初始化工作略去
- // 我們在這裡設定View的layout的Id為layoutId_A
- currentContentFlag = ViewA;
- setViewContent(R.layout.layoutId_A, new ConfigViewInterface() { // 傳進去一個接口,并覆寫裡面的方法
- public void setView(View view) {
- setViewA(view);
- }
- });
- }
- private void setViewContent(int layoutId, ConfigViewInterface configViewInterface) {
- view = LayoutInflater.from(this).inflate(layoutId, null); // 設定View的内容
- configViewInterface.setView(view);
- }
- private setViewA(View view) {
- }
- private setViewB(View view) {
- }
- private interface ConfigViewInterface {
- void setView(View view) ;
- }
- }
這樣是不是就好多了呢?慢慢了解下上面的代碼,多少會對你有幫助的。有時候學知識,就要所練,可能當時不了解某個點,不知什麼時候突然就懂了。
歡迎拍磚。