1. 程式人生 > >android下的callback機制

android下的callback機制

按照我個人的理解,就是: 用java的回撥機制來實現C語言中的函式指標的傳遞

為了瞭解什麼是回撥函式,在網上查閱瞭如下資料,整理如下:

資料一:

首先說說什麼叫回調函式?

    在WINDOWS中,程式設計師想讓系統DLL呼叫自己編寫的一個方法,於是利用DLL當中回撥函式(CALLBACK)的介面來編寫程式,使它呼叫,這個就 稱為回撥。在呼叫介面時,需要嚴格的按照定義的引數和方法呼叫,並且需要處理函式的非同步,否則會導致程式的崩潰。  

這樣的解釋似乎還是比較難懂,這裡舉個簡 單的例子:

    程式設計師A寫了一段程式(程式a),其中預留有回撥函式介面,並封裝好了該程式。程式設計師B要讓a呼叫自己的程式b中的一個方法,於是,他通過a中的介面回撥自己b中的方法。目的達到。   

    在C/C++中,要用回撥函式,被掉函式需要告訴呼叫者自己的指標地址,但在JAVA中沒有指標,怎麼辦?我們可以通過介面(interface)來實現定義回撥函式。

    假設我是程式設計師A,以下是我的程式a:

  1. publicclass Caller {      
  2.         public MyCallInterface mc;    
  3.         publicvoid setCallfuc(MyCallInterface mc){  
  4.               this.mc= mc;      
  5.         }  
  6.           publicvoid call(){  
  7.              this
    .mc.method();  
  8.         }  
  9.     }      


 我還需要定義一個介面,以便程式設計師B根據我的定義編寫程式實現介面。

  1. publicinterface MyCallInterface {  
  2.            publicvoid method();  
  3.     }       

於是,程式設計師B只需要實現這個介面就能達到回撥的目的了,以下是程式b:

  1. publicclass B implements MyCallInterface {  
  2.          publicvoid method() {  
  3.                 System.out.println("誰來呼叫我啊。好寂寞!!"
    );      
  4.          }  
  5.          publicstaticvoid main(String args[]) {  
  6.                Caller call = new Caller();  
  7.                call.setCallfuc(new B());         
  8.                call.call();      
  9.          }  
  10.    }  

===============================================================================================

===============================================================================================

資料二:

所謂回撥,就是客戶程式C呼叫服務程式S中的某個方法a,然後S又在某個時候反過來呼叫C中的某個方法b,對於C來說,這個b便叫做回撥函式。

一般說來,C不會自己呼叫b,C提供b的目的就是讓S來呼叫它,而且是C不得不提供。由於S並不知道C提供的b叫甚名誰,所以S會約定b的介面規範(函式原型),然後由C提前通過S的一個函式r告訴S自己將要使用b函式,這個過程稱為回撥函式的註冊,r稱為註冊函式。

下面舉個通俗的例子:

某天,我打電話向你請教問題,當然是個難題,:),你一時想不出解決方法,我又不能拿著電話在那裡傻等,於是我們約定:等你想出辦法後打手機通知我,這樣,我就掛掉電話辦其它事情去了。過了XX分鐘,我的手機響了,你興高采烈的說問題已經搞定,應該如此這般處理。故事到此結束。

這個例子說明了“非同步+回撥”的程式設計模式。其中,你後來打手機告訴我結果便是一個“回撥”過程;我的手機號碼必須在以前告訴你,這便是註冊回撥函式;我的手機號碼應該有效並且手機能夠接收到你的呼叫,這是回撥函式必須符合介面規範。

如果你還不太清楚看看這段描述合和程式碼:

宣告一個介面,另外一個類有方法裡面有個引數以是這個介面型別的,而後在另外類中實現這個介面(java中多用的是匿名內部類),而且以這個匿名的類生成的物件為引數傳到上面提到類中,而後實現回撥.......這種用法可以參考java裡面常用到的資料庫操作所用到的幾個介面.....

  1. //宣告一個介面
  2. publicinterface ICallBack {  
  3.     void postExec();  
  4. }  
  5. //另外一個類有方法裡面有個引數以是這個介面型別的
  6. publicclass FooBar {  
  7.     private ICallBack callBack;  
  8.     publicvoid setCallBack(ICallBack callBack) {  
  9.         this.callBack = callBack;  
  10.     }  
  11.     publicvoid doSth() {  
  12.         callBack.postExec();  
  13.     }  
  14. }  


回撥的實現:

  1. publicclass Test {  
  2.     publicstaticvoid main(String[] args) {  
  3.         FooBar foo = new FooBar();  
  4.         foo.setCallBack(new ICallBack() {  
  5.             publicvoid postExec() {  
  6.                 System.out.println("method executed.");  
  7.             }  
  8.         });  
  9.         foo.doSth();//呼叫函式
  10.     }  
  11. }  

===============================================================================================

===============================================================================================

資料三:一個利用回撥函式的經典例子

下面使用java回撥函式來實現一個測試函式執行時間的工具類:

如果我們要測試一個類的方法的執行時間,通常我們會這樣做:

java 程式碼

  1. publicclass  TestObject {     
  2.     /**    
  3.      * 一個用來被測試的方法,進行了一個比較耗時的迴圈    
  4.      */
  5.     publicstaticvoid  testMethod(){     
  6.         for ( int  i= 0 ; i< 100000000 ; i++){     
  7.         }     
  8.     }     
  9.     /**    
  10.      * 一個簡單的測試方法執行時間的方法    
  11.      */
  12.     publicvoid  testTime(){     
  13.         long  begin = System.currentTimeMillis(); //測試起始時間    
  14.         testMethod(); //測試方法    
  15.         long  end = System.currentTimeMillis(); //測試結束時間    
  16.         System.out.println("[use time]:"  + (end - begin)); //列印使用時間    
  17.     }     
  18.     publicstaticvoid  main(String[] args) {     
  19.         TestObject test=new  TestObject();     
  20.         test.testTime();     
  21.     }     
  22. }    

大家看到了testTime()方法,就只有"//測試方法"是需要改變的,下面我們來做一個函式實現相同功能但更靈活:

首先定一個回撥介面:

java 程式碼
 
public   interface  CallBack {   
    //執行回撥操作的方法    
    void  execute();   
}  

然後再寫一個工具類:

java 程式碼

  1. publicclass  Tools {     
  2.     /**    
  3.      * 測試函式使用時間,通過定義CallBack介面的execute方法    
  4.      * @param callBack    
  5.      */
  6.     publicvoid  testTime(CallBack callBack) {     
  7.         long  begin = System.currentTimeMillis(); //測試起始時間    
  8.         callBack.execute(); ///進行回撥操作    
  9.         long  end = System.currentTimeMillis(); //測試結束時間    
  10.         System.out.println("[use time]:"  + (end - begin)); //列印使用時間    
  11.     }     
  12.     publicstaticvoid  main(String[] args) {     
  13.         Tools tool = new  Tools();     
  14.         tool.testTime(new  CallBack(){     
  15.             //定義execute方法    
  16.             publicvoid  execute(){     
  17.                 //這裡可以加放一個或多個要測試執行時間的方法    
  18.                 TestObject.testMethod();     
  19.             }     
  20.         });     
  21.     }     
  22. }    


大家看到,testTime()傳入定義callback介面的execute()方法就可以實現回撥功能