不知道是我學Java的時候沒有認真聽還是怎么的,曾經一直不知道什么是“回調”,它有什么用,百度一大堆,都太復雜看不明白(好吧是我笨),所以想把自己理解的分享給其他看到的人,大家都真正認識一下這個重要的機制。
如果你要進行Android開發,那么回調肯定是會經常用到的,為什么?下面慢慢來說,大牛其實這個地方已經可以離開了......
先從簡單的開始,什么是回調?
Java允許我們調用接口的方法,但是有一個前提,就是編譯的時候接口的對象必須是一個具體的類,並且這個類實現了接口。當我們調用接口的方法的時候,接口的具體子類中的具體方法會被調用,這就是回調。嗯,我說什么鬼?還是上代碼吧。
public interface A { void printClassName(); }
public class B implements A { public void printClassName() { System.out.println("This is class B!"); } }
public static void main(String[] args) { A a = new B(); a.printClassName(); }
輸出的結果如下:

從上面的代碼可以看到,我們在主函數中定義了接口A,也調用了接口A的方法,但是要注意,我們實例化的時候其實new的是一個實現了A接口的具體類,我們調用A中的printClassName方法的時候Java就會去回調B中的該方法。這樣做的優點是什么?就是我們在調用的時候,可以完全不管A的子類是如何實現A中的方法的,只需要調用這個方法即可,怎么實現,我們不管,那是子類的事情了,這樣其實是解耦的一種很好的方法,如果我們要修改為別的類,只需要把new后面的子類改掉就好。
是不是很簡單?如果代碼你都懂,那么恭喜你,你已經距離成功只有一步之遙了。
說回Androd,其實里面是有很多地方用到這個機制的,我們也是從簡單的說起。
很多時候,我們對某個控件實現點擊事件的監聽,會像下面這樣做:
Button btn = new Button(this); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // doSth } });
很多人都覺得,這樣很直接明了啊,可是如果我問你,為什么我們要new一個OnClickListener進去呢?如果你不知道,證明你還不完全了解回調。按照我們上面所說的,我們可以調用接口的方法,但是接口需要一個具體的實現,所以我們應該知道,setOnClickListener中的參數應該是一個接口,不信?我們一起看看源碼
public interface OnClickListener { /** * Called when a view has been clicked. * * @param v The view that was clicked. */ void onClick(View v); }
果然,接口中還有一個onClick方法。既然是回調,我們再看看這個方法在哪里被調用了
先看setOnClickListener方法
public void setOnClickListener(@Nullable OnClickListener l) { if (!isClickable()) { setClickable(true); } getListenerInfo().mOnClickListener = l; }
關鍵是把OnClickListener的對象賦值給了ListenerInfo的mOnClickListener,我們再看下去
public boolean performClick() { final boolean result; final ListenerInfo li = mListenerInfo; if (li != null && li.mOnClickListener != null) { playSoundEffect(SoundEffectConstants.CLICK); li.mOnClickListener.onClick(this); result = true; } else { result = false; } sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED); return result; }
我們看到在這個叫做performClick的方法中調用了onClick方法,還有另外一個叫做callOnClick的方法也會調用onClick,區別可以去看看源碼的說明,這里不詳細。那么這兩個方法又在什么時候被執行的呢?其實他們都是在屏幕接收到點擊信號的時候,把數據一層一層的往上傳遞給framework,由framework來調用。對於了解回調,我覺得到這里就足夠了,再往下就有點偏了。
要明白的一點就是,在這個類中,調用的是接口的方法。現在你應該明白了吧,為什么我們要new一個OnClickListener的子類呢?就是讓編譯器知道,調用接口方法的時候,去回調我們設置的OnClickListener子類的對應方法。
如果到這里你都懂了,很好,我們再說多一些,具體一些。
究竟我們知道了這個機制之后,它有什么用呢?一般來說,用得比較多,就是通信以及MVP模式
通信,其實就是不同組件之間的通信,可以是Fragment和Activity,也可以是Adapter和Activity,這里不詳細說太多,可以看看之前的博文:http://www.cnblogs.com/Fndroid/p/5187444.html
上面我們說到了MVP,這個模式真的很重要,對於比較大的項目來說,意義很深遠,既能幫助我們解耦不堪重負的Activity,也能便於我們維護和擴展,有興趣可以參考下面這個項目:https://github.com/bboyfeiyu/the-tech-frontier-app
