天天看點

安卓回調機制什麼是自定義回調函數?        一個簡單的自定義回調函數的例子

寫安卓這麼久了,對于回調一直沒有深入研究。其實所謂的回調函數就是:在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

  1. public interface MyInterface {  
  2.     void sayYourName();  
  3. }  

        接着,我們定義一個類,其中一個方法以接口MyInterface類型的對象作為參數:

[java] view plain copy

  1. public class MyClass {  
  2.     public MyClass() {  
  3.         Log.e("WangJ", "MyClass-constructor");         //标注構造函數  
  4.     }  
  5.     public void sayYourName(MyInterface myInterface){  
  6.         Log.e("WangJ", "MyClass-sayYourName_start");    //标注方法開始  
  7.         myInterface.sayYourName();                      //遇到不知道具體實作的時候就用接口的抽象方法  
  8.         Log.e("WangJ", "MyClass-sayYourName_finish");   //方法結束  
  9.     }  
  10. }  

        最後,我們在Activity中調用這個類,建立對象并調用其方法,期間實作接口中抽象方法的具體實作邏輯,供回調使用:

[java] view plain copy

  1. public class MainActivity extends Activity {  
  2.     @Override  
  3.     protected void onCreate(Bundle savedInstanceState) {  
  4.         super.onCreate(savedInstanceState);  
  5.         setContentView(R.layout.activity_main);  
  6.         MyClass myClass = new MyClass();  
  7.         myClass.sayYourName(new MyInterface() {                     //實作接口并作為參數傳入  
  8.             @Override  
  9.             public void sayYourName() {  
  10.                 Log.e("WangJ", "callBack-interface-implementor");    //具體操作實作  
  11.             }  
  12.         });  
  13.     }  
  14. }  

        好了,運作一下(我們這個例子沒有任何界面,即預設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

  1. class MyActivity extends Activity {  
  2.     View view;  
  3.     int currentContentFlag;  
  4.     private static final int ViewA = 1; // 标志着目前View顯示的内容是ViewA  
  5.     private static final int ViewB = 2; // 标志着目前View顯示的内容是ViewB  
  6.     @Override  
  7.     public void onCreate(Bundle savedInstanceState) {  
  8.         super.onCreate(savedInstanceState);  
  9.         setContentView(R.layout.activity_main);  
  10.         // 一些例如對view初始化工作略去  
  11.         // 我們在這裡設定View的layout的Id為layoutId_A  
  12.         currentContentFlag = ViewA; // 修改目前顯示内容的flag,告訴這個setViewContent函數裡面到底執行setViewA還是setViewB  
  13.         setViewContent(R.layout.layoutId_A);  
  14.     }  
  15.     private void setViewContent(int layoutId) {  
  16.         view = LayoutInflater.from(this).inflate(layoutId, null); // 設定View的内容  
  17.         switch (currentContentFlag) {  
  18.             case ViewA:  
  19.                 // 說明目前View的内容是ViewA,在這裡用代碼對ViewA裡面的東西進行具體設定  
  20.                 setViewA(view);  
  21.                 break;  
  22.             case ViewB:  
  23.                 // 說明目前View的内容是ViewB,在這裡用代碼對ViewB裡面的東西進行具體設定  
  24.                 setViewB(view);  
  25.                 break;  
  26.             default :  
  27.                 break;  
  28.         }  
  29.     }  
  30.     private setViewA(View view) {  
  31.     }  
  32.     private setViewB(View view) {  
  33.     }  
  34. }  

  這樣的話,每設定一次View的内容,都要修改目前顯示内容的flag,通過維護這個flag變量,來告訴這個setViewContent函數裡面到底執行setViewA還是setViewB。

  這樣做可不可行呢?實作肯定也可以實作,但是,我想到了用回調機制來完成這件事。

  什麼是回調呢?回調回調,回去調用。我了解回調,就是,在代碼執行的過程中,函數FunA()某一時刻被調用,那麼将轉去執行FunA(),在FunA執行的時候呢,又反過來去執行原代碼裡的一些東西。這應該是最淺顯的解釋了吧。

  在Java語言裡面,我們可以通過interface實作自己的回調,Java裡面的interface真的太有用了。則上面的代碼可以改為下面的實作:

[java] view plain copy

  1. class MyActivity extends Activity {  
  2.     View view;  
  3.     @Override  
  4.     public void onCreate(Bundle savedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6.         setContentView(R.layout.activity_main);  
  7.         // 一些例如對view初始化工作略去  
  8.         // 我們在這裡設定View的layout的Id為layoutId_A  
  9.         currentContentFlag = ViewA;   
  10.         setViewContent(R.layout.layoutId_A, new ConfigViewInterface() { // 傳進去一個接口,并覆寫裡面的方法  
  11.             public void setView(View view) {  
  12.                 setViewA(view);  
  13.             }  
  14.         });  
  15.     }  
  16.     private void setViewContent(int layoutId, ConfigViewInterface configViewInterface) {  
  17.         view = LayoutInflater.from(this).inflate(layoutId, null); // 設定View的内容  
  18.         configViewInterface.setView(view);  
  19.     }  
  20.     private setViewA(View view) {  
  21.     }  
  22.     private setViewB(View view) {  
  23.     }  
  24.     private interface ConfigViewInterface {  
  25.         void setView(View view) ;  
  26.     }  
  27. }  

  這樣是不是就好多了呢?慢慢了解下上面的代碼,多少會對你有幫助的。有時候學知識,就要所練,可能當時不了解某個點,不知什麼時候突然就懂了。

  歡迎拍磚。