淺析android系統設計中的回調思想

1、爲什麼寫做本文
  在慢慢深刻接觸android開發的過程當中,我愈來愈發現android中(至少應用曾的開發)用到了不少回調的思想。好比activity的生命週期,fragment的生命週期,皆是回調函數實現的,android中的事件處理機制其一就是回調,線程方面的異步任務、loader、hanlder等都是基於回調的,等等。java

  可見android的其一根本思想就是回調,須要你來參與時,回調用相關的回調方法,你來填充。android

  能夠說回調的思想浸潤與android設計的方方面面,android開發中幾乎帶有on的方法都是回調方法。做爲一名致力於深刻學習移動開發的菜鳥,深刻理解回調就顯得很是必要了。編程

2、爲什麼要引入回調
  回調是不得以而爲之的設計策略,想象一種系統實現:在一個下載系統中有一個文件下載模塊和一個下載文件當前進度顯示模塊,系統要求實時的顯示文件的下載進度,想一想很簡單,在面向對象的世界裏無非是實現兩個類而已。可是問題偏偏出在這裏,顯示模塊如何驅動下載進度條?顯示模塊不知道也不該該知道下載模塊所知道的文件下載進度(面向對象設計的封裝性,模塊間要解耦,模塊內要內聚),文件下載進度是隻有下載模塊才知道的事情,解決方案很簡單給下載模塊傳遞一個函數指針做爲回調函數驅動顯示模塊的顯示進度。設計模式

  在面向對象的世界中這樣的例子還真很多,形成這樣的問題的根源,相信你們已經從上面的敘述中體會到了,就是面向對象的程序設計思想,就是設計模式中要求的模塊獨立性,高內聚低耦合等特性。api

  封裝變化的編程策略給編程人員第一位的指導思想就是面向接口編程,即設計模式中提到的面向虛擬編程而不是面向實現。這樣的編程思想極大地革新了編程世界,能夠說沒有這一原則就沒有面向對象的程序設計,這一原則給程序設計一種指導思想:即如何更高的將現實模型映射成程序模型。這樣的設計思想在極大地催生高度獨立性模塊的同時削弱了模塊間的協做性,也就是耦合性,它使得模塊間更多的從事着單向的調用工做,一個模塊須要某種服務就去找另外一個模塊,這使得程序呈現出層次性,高層經過接口調用底層,底層提供服務。可是現實世界中嚴格遵循現層次特性的系統是不多見的,絕對的MVC是不存在的,由於更多的模塊要求通並協做,可見沒有耦合就沒有協做沒有好的調用關係,耦合真的不是錯。異步

  既然咱們須要模塊間的協做,同時咱們又厭惡的摒棄模塊間你中有我我中有你的曖昧關係那如何生成系統呢,答案是函數指針(不必定是函數指針)也就是使用回調的方式。若是一個對象關心另外一個對象的狀態變化那麼給狀態的變化註冊回調函數讓它通知你這類狀態的改變,這樣在封裝了模塊變化的同時實現了模塊間的協做關係另闢獨徑的給對象解耦。ide

3、回調的通俗理解
  你餓了,想吃飯,就一會去問你媽一聲」開飯沒有啊?」這就是正常函數調用.函數

  可是今天你媽包餃子,花的時間比較長,你跑啊跑啊,就煩了.因而你給你媽說,我先出去玩會,開飯的時候打我手機.等過了一陣,你媽給你打電話說」開飯啦,快回來吃飯吧!」學習

  其中,你告訴你媽打手機找你,就是個你把回調函數句柄保存到你媽的動做.你媽打電話叫你,就是個回調過程.測試

4、回調的詳細解釋
理解方式1:通常寫程序是你調用系統的API,這個過程叫Call。若是把關係反過來,你寫一個函數,讓系統調用你的函數,那就是回調(CallBack)了,那個被系統調用的函數就是回調函數。放到android中,咱們通常是調用framwork定義的api,可是若是咱們寫了一個方法,由framwork來調用,這個方法就是回調函數。

理解方式2:所謂回調函數,其運行方式是,「你不用調用我,等着我來調用你」。回調的意思是在你執行某個語句後成功了,再執行你傳遞進來的function,在作異步處理的時候特別有用。

理解方式3:歸程序本質,刨除那些面向對象的概念,回調函數就是一個經過函數指針調用的函數。就是用函數指針作參數。那個函數指針就是回調函數。

  回調是編程層面的設計模式,不是基於語言的。在C/C++中,要用回調函數,被調函數須要告訴調用者本身的指針地址,但在JAVA中沒有指針,怎麼辦?咱們能夠經過接口(interface)來實現定義回調函數。在.Net的世界裏Delegate ==Callback。

 

5、在android中怎麼使用回調呢
JAVA的CALLBACK經過接口來實現。
例:
1.class A,class B
2.class A實現接口operate
3.class B擁有一個參數爲operate接口類型的函數test(operate o)
4.class A運行時調用class B中test函數,以自身傳入參數
5.class B已取得A,就能夠隨時回調A所實現的operate接口中的方法

6、簡明案例
  以媽媽喊兒子吃飯爲例,貼代碼以下:

//java實現回調,採用接口作回調函數
public interface CallBack { void eat(); }
/* * * 兒子要去玩遊戲,不願乖乖坐在那裏等飯作好。 * 因此,他須要先問媽媽飯作好了沒?即正常函數調用 : call askMom() * 沒有就去玩遊戲,等媽媽飯作好了,再來叫他吃飯即函數回調: callback eat() * */
public class Son implements CallBack { //son持有mom的引用.
    private Mom mom; public void setMom(Mom mom){ this.mom = mom; } public void eat() { System.out.println("兒子:我來吃飯了"); } public void askMom(){ //經過對mom的引用調用含有接口參數的方法
        System.out.println("兒子:飯作好了嗎"); System.out.println("兒子:沒作好的話,我去玩遊戲了"); new Thread(new Runnable() { @Override public void run() { mom.doCook(Son.this); } }).start(); }
}
/* * 調用回調函數的對象:媽媽 */
public class Mom { public void doCook(final CallBack callBack){ new Thread(new Runnable() { public void run() { System.out.println("媽媽:還沒作好...."); try { Thread.sleep(5000); System.out.println("\n"); System.out.println("------5秒後------"); System.out.println("媽媽:飯作好了,兒子快過來吃飯了"); //調用回調函數,喊來兒子來吃飯
 callBack.eat(); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } }
/* * 測試案例 */
public class Test { public static void main(String[] args) { Mom mom = new Mom(); Son son = new Son(); son.setMom(mom); son.askMom(); } }
運行結果: 兒子:飯作好了嗎 兒子:沒作好的話,我去玩遊戲了 媽媽:還沒作好.... ------5秒後------ 媽媽:飯作好了,兒子快過來吃飯了 兒子:我來吃飯了

 

 

7、回調用在哪裏
回調函數主要用於一些比較費時的操做,或響應不知道什麼時候將會發生的事件,場合異步結合(異步其實就是重開一個線程)。

當兩個對象之間須要進行一些協同操做時,常使用回調函數,好比一個對象想得到另外一個對象內部的某些數據。

8、回調的優勢
回調函數使得程序設計更加靈活。

實現模塊獨立性,將實現者和調用者分離,符合面對對象高內聚低耦合的設計思想。

9、回調的缺點
代碼的易讀性很差。

 

轉載:https://blog.csdn.net/a910626/article/details/45920893 

相關文章
相關標籤/搜索