Java&Android中的回調機制

Java&Android中的回調機制

一、簡介

Android中普遍存在着各種回調。如果不懂回調,對很多知識只能是一知半解。所以我決定今兒就好好研究下Java中的回調機制。下面是我的理解過程。

二、理解

1. 知乎說

出自常溪玲的知乎:http://www.zhihu.com/question/19801131/answer/13005983

你到一個商店買東西,剛好你要的東西沒有貨,於是你在店員那裏留下了你的電話,過了幾天店裏有貨了,店員就打了你的電話,然後你接到電話後就到店裏去取了貨。在這個例子裏,你的電話號碼就叫回調函數,你把電話留給店員就叫登記回調函數,店裏後來有貨了叫做觸發了回調關聯的事件,店員給你打電話叫做調用回調函數,你到店裏去取貨叫做響應回調事件。回答完畢。

2. 博客說

出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/17483273

有一天小王遇到一個很難的問題,問題是“1 + 1 = ?”,就打電話問小李,小李一下子也不知道,就跟小王說,等我辦完手上的事情,就去想想答案,小王也不會傻傻的拿着電話去等小李的答案吧,於是小王就對小李說,我還要去逛街,你知道了答案就打我電話告訴我,於是掛了電話,自己辦自己的事情,過了一個小時,小李打了小王的電話,告訴他答案是2。下面是代碼展示:

/**
 * 這是一個回調接口
 * @author xiaanming
 */
public interface CallBack {
    /**
     * 這個是小李知道答案時要調用的函數告訴小王,也就是回調函數
     * @param result 是答案
     */
    public void solve(String result);
}
/**
 * 這個是小王
 * @author xiaanming
 * 實現了一個回調接口CallBack,相當於----->背景一
 */
public class Wang implements CallBack {
    /**
     * 小李對象的引用
     * 相當於----->背景二
     */
    private Li li; 
    /**
     * 小王的構造方法,持有小李的引用
     * @param li
     */
    public Wang(Li li){
        this.li = li;
    }
    /**
     * 小王通過這個方法去問小李的問題
     * @param question  就是小王要問的問題,1 + 1 = ?
     */
    public void askQuestion(final String question){
        //這裏用一個線程就是異步,
        new Thread(new Runnable() {
            @Override
            public void run() {
                /**
                 * 小王調用小李中的方法,在這裏註冊回調接口
                 * 這就相當於A類調用B的方法C
                 */
                li.executeMessage(Wang.this, question); 
            }
        }).start();     
        //小網問完問題掛掉電話就去幹其他的事情了,誑街去了
        play();
    }
    public void play(){
        System.out.println("我要逛街去了");
    }
    /**
     * 小李知道答案後調用此方法告訴小王,就是所謂的小王的回調方法
     */
    @Override
    public void solve(String result) {
        System.out.println("小李告訴小王的答案是--->" + result);
    }
}
/**
 * 這個就是小李啦
 * @author xiaanming
 */
public class Li {
    /**
     * 相當於B類有參數爲CallBack callBack的f()---->背景三
     * @param callBack  
     * @param question  小王問的問題
     */
    public void executeMessage(CallBack callBack, String question){
        System.out.println("小王問的問題--->" + question);
        //模擬小李辦自己的事情需要很長時間
        for(int i=0; i<10000;i++){
        }
        /**
         * 小李辦完自己的事情之後想到了答案是2
         */
        String result = "答案是2";
        /**
         * 於是就打電話告訴小王,調用小王中的方法
         * 這就相當於B類反過來調用A的方法D
         */
        callBack.solve(result); 
    }
}
/**
 * 測試類
 * @author xiaanming
 */
public class Test {
    public static void main(String[]args){
        /**
         * new 一個小李
         */
        Li li = new Li();
        /**
         * new 一個小王
         */
        Wang wang = new Wang(li);
        /**
         * 小王問小李問題
         */
        wang.askQuestion("1 + 1 = ?");
    }
}

3. 我說

小王和小李可以通信的前提是相互擁有對方的引用,可以把小李當作一個博識的人,他可以回答很多人很多問題,小王則是其中一個好問問題的人。小王直接擁有小李的引用並通過引用調用小李暴露的executeMessage(CallBack callBack, String question)方法向小李提問,並把自身的引用通過接口的方式暴露給小李。小李得知答案後,通過小王暴露的接口方法回答小王的問題。

小王爲什麼要用接口方式提供引用給小李呢?這是因爲如果直接給出小王的引用給小李的話,小李就只能解答小王的問題,而不能解答其他人的問題。而接口具有通用性,只要有人實現瞭解答的接口,小李就可以給他提供解答的服務。親畫圖如下:

接下來就不難理解下面的經典的回調方式了(●’◡’●)

4. 經典的回調方式

  • class A實現接口CallBack callback——背景1
  • class A中包含一個class B的引用b ——背景2
  • class B有一個參數爲callback的方法f(CallBack callback) ——背景3
  • A的對象a調用B的方法 f(CallBack callback) ——A類調用B類的某個方法 C
  • 然後b就可以在f(CallBack callback)方法中調用A的方法 ——B類調用A類的某個方法D

三、經典的回調案例

1. 線程的run()方法

  • class A實現runnable接口,具有公共的run()方法
  • class A中包含一個class Thread的引用b
  • class Thread中有一個參數爲target的方法Thread(Runnable target)
  • A的對象a調用Thread的方法Thread(Runnable target),其實就是構造方法
  • b在Thread(Runnable target)方法中調用A的方法run()方法,這是虛擬機調用的
public Thread(Runnable target) {
    init(null, target, "Thread-" + nextThreadNum(), 0);
}

2. View的onClick()方法

  • Activity實現View.OnClickListener接口,具有公共的onClick()方法
  • Activity中包含一個View的引用view
  • View中有一個參數爲l的方法setOnclickListener(OnClickListener l)
  • Activity中的view調用setOnclickListener(OnClickListener l),傳入自身的引用
  • view在setOnclickListener(OnClickListener l)中調用Activity中的onClick()方法

四、如何自己寫回調呢?

  1. 準備回調接口,設計回調方法
  2. 顧客實現回調接口,包含回調方法
  3. 顧客包含店家的引用
  4. 店家包含一個以接口爲參數的註冊回調方法
  5. 顧客調用註冊回調方法
  6. 店家在註冊回調方法中回調顧客的方法

簡單點說:

  1. 顧客擁有店家的引用
  2. 顧客通過接口暴露自身的方法給店家
  3. 店家暴露方法給顧客,讓顧客傳入自身的引用給店家
  4. 店家通過顧客傳入的引用調用顧客的方法

再簡單點說:

  1. 雙方都擁有對方的引用
  2. 一方通過調用對方的方法觸發回調
  3. 另一方通過調用對方的方法響應回調
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章