Android 何爲回調接口,回調機制詳解

首先解決啥是回調:

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


C不會自己調用b,C提供b的目的就是讓S來調用它,而且C不得不提供。S並不知道C提供的b是什麼,因此S會約定b的接口規範(函數原型),然後由C提前通過S的一個函數r告訴S自己將要使用b函數(即註冊)。r爲註冊函數。

簡單來說:回調函數就是預留給系統調用的函數,而且我們往往知道該函數被調用的時機,那我們繼續完善下上面的那幅圖。


看着這幅圖,其實我們回想一下,會發現,生活中到處都有回調這種思想存在。軟件的很多思想其實只是我們實際生活中思維方式的一種轉化。

我們平時考試答題的第一件事是幹嘛?沒錯,是寫上學號和姓名。這裏注意了,我們填寫學號和姓名不是給自己看的(即該方法不是給自己調用的),而是給老師登記分數時看的(預留給系統將來調用),這其實就是一個回調的應用。老師提供接口(輸入姓名,學號規則),我們利用接口註冊。


看到上面的小示例,大家對回調就有了一些瞭解了,我們再回到文章剛開始的例子。
那個例子說明了“異步+回調”的編程模式。其中,你後來打手機告訴我結果便是一個“回調”過程;我的手機號碼必須在以前告訴你,這便是註冊回調函數;我的手機號碼應該有效並且手機能夠接收到你的呼叫,這是回調函數必須符合接口規範。


我們已經大概知道了回調的基本流程,下面,來看看Android中回調的基本使用。

場景一:

[java] view plain copy
 print?
  1. Button button = (Button)this.findViewById(R.id.button);    
  2. button.setOnClickListener(newButton.OnClickListener() {    
  3.    //回調函數    
  4.    @override    
  5.    publicvoidonClick(View v) {    
  6.       buttonTextView.setText("按鈕被點擊了");    
  7.    }    
  8. });    


上面的代碼給按鈕加了一個事件監聽器,這其實就是“回調”最常見的應用場景之一。我們自己不會顯式地去調用onClick方法。用戶觸發了該按鈕的點擊事件後,它會由Android系統來自動調用。

場景二:

[java] view plain copy
 print?
  1. @Override    
  2. publicvoidonCreate(BundlesaveInstanceState) {    
  3.    super.onCreate(saveInstanceState);    
  4.    // You code...    
  5. }    
  6. @Override    
  7. publicvoidonResume() {    
  8.    super.onResume();    
  9.    // You code...    
  10. }    


Activity的整個生命週期基本上都說回調函數在發揮作用。

看了兩個我們經常使用的回調方式,我們先來總結下android利用回調的基本方法。其實,只是把我們的那張圖翻譯了下。


--你類--

[java] view plain copy
 print?
  1. package lin.callback.test;  
  2.    
  3. public class You implements Runnable{  
  4.    
  5.        
  6.     private String who;  
  7.      private ContactInterface callBack;    
  8.      public You() {  
  9.             // TODO Auto-generated constructor stub  
  10.      }  
  11.         
  12.     //調用此方法就表示有人聯繫你了,註冊到你這來  
  13.      public void setCallBack(String who,String question,ContactInterface callBack) {  
  14.          this.who = who;      
  15.          System.out.println("你說:當前聯繫到我的人是"+who+",問題是"+question);  
  16.          this.callBack =callBack;  
  17.      }  
  18.           
  19.      public void handleThings(){  
  20.          //假如你現在正在想問題的答案,需要一點時間  
  21.          for(int i=0;i<100000;i++){    
  22.                if(i == 0){  
  23.                    System.out.println("你正在思考問題.....");  
  24.                }  
  25.          }  
  26.             
  27.          String answer = "答案是A";  
  28.          //想到問題的辦法了  
  29.          System.out.println("你說:想到答案了,準備打回去給"+who+"告訴他答案");  
  30.          callBack.callBackByTel(answer);  
  31.      }  
  32.    
  33.     /* (non-Javadoc) 
  34.      * @see java.lang.Runnable#run() 
  35.      */  
  36.     @Override  
  37.     public void run() {  
  38.         try {  
  39.             Thread.sleep(1000);  
  40.             handleThings();  
  41.         } catch (Exception e) {  
  42.             e.printStackTrace();  
  43.         }  
  44.     }   
  45. }  


--我類--

[java] view plain copy
 print?
  1. public class Me {  
  2.    
  3.      public static void main(String[] args){    
  4.             
  5.          Me me = new Me();  
  6.          me.hasQuestion();  
  7.             
  8.      }  
  9.         
  10.      private void hasQuestion(){  
  11.          //現在有問題想不出來答案,想去問你  
  12.          You you = new You();  
  13.          you.setCallBack("蝸牛""某道題答案是什麼?"new ContactInterface() {  
  14.                
  15.             @Override  
  16.             public void callBackByTel(String answer) {  
  17.                 System.out.println("我說:嗯,好的,我收到答案了:"+answer+",謝謝");  
  18.                    
  19.             }  
  20.         });  
  21.         //你接到電話,起牀開始思考問題  
  22.         new Thread(you).start();  
  23.      }  
  24. }  


--接口類(規範)--

[java] view plain copy
 print?
  1. public interface ContactInterface {  
  2.        
  3.     public void callBackByTel(String answer);  
  4.        
  5. }  
驗證結果:
你說:當前聯繫到我的人是蝸牛,問題是某道題答案是什麼?
你正在思考問題
你說:想到問題了,準備打回去給蝸牛告訴他答案
我說:嗯,好的,我收到答案了:答案是A,謝謝


對回調的深入思考:

程序的本質就是代碼跳轉,不管同步異步反射接口虛函數,本質上都是函數調用。函數我們要調用它,就需要它的指針,不同語言通過不同的方式來得到這個指針。而我們定義的接口其實就是一個函數指針,那麼那個註冊過程,其實就是相當於對那個函數指針賦值。通過這個函數指針來調用我們定義的自實現函數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章