什么是接口回調?


一般來說,模塊之間都存在一定的調用關系,從調用方式上看,可以分為三類:同步調用、異步調用和回調。同步調用是一種阻塞式調用,即在函數A的函數體里通過書寫函數B的函數名來調用之,使內存中對應函數B的代碼得以執行。異步調用是一種類似消息或事件的機制解決了同步阻塞的問題,例如 A通知 B后,他們各走各的路,互不影響,不用像同步調用那樣, A通知 B后,非得等到 B走完后, A才繼續走 。回調是一種雙向的調用模式,也就是說,被調用的接口被調用時也會調用對方的接口,例如A要調用B,B在執行完又要調用A。

回調一般用於層間協作,上層將本層函數安裝在下層,這個函數就是回調,而下層在一定條件下觸發回調。例如作為一個驅動,是一個底層,他在收到一個數據時,除了完成本層的處理工作外,還將進行回調,將這個數據交給上層應用層來做進一步處理,這在分層的數據通信中很普遍。

java接口回調機制想必大家並不陌生,其思想簡單,應用廣泛,如網絡請求、界面的點擊監聽等,是一個java開發者必須要掌握的基本思想之一。

我們在做java開發時經常會遇到文件下載、請求服務器數據等基本操作,大家都知道網絡請求屬於耗時操作,我們如果在直接主線程執行這些邏輯時很可能會造成主線程堵塞,從而導致程序崩潰。我們通常都是開啟一個子線程來執行網絡請求操作。

    public void doSomeWork() {
        new Thread(new Runnable() {
            @Override
            public void run() {

                    // 執行邏輯,發起網絡請求,如請求后台數據,下載文件等

            }
        }).start();
}

上面這段代碼想必你已經再熟悉不過了,不過當我們在做一次開發時,經常會多次使用網絡請求,比如多次請求服務器的數據,所以我們更願意將其寫成一個小框架: 

public String doRequest(String url) {
        new Thread(new Runnable() {
            @Override
            public void run() {

                    // 執行邏輯,請求后台json數據

            }
        }).start();
        //將獲取的數據轉化為String,並返回
    }

那么問題來了: 我們在寫成框架時,網絡請求是在子線程中進行的,很可能數據還沒返回來的時候,doRequest方法就已經執行完了,那么這時候返回的數據就沒有任何意義了,最終的結果是我們得到的String為空的,而不是我們期待的的數據。

解決此問題的一種方法: 子線程請求到數據后,直接對數據進行處理(缺陷:失去了框架的意義)

public void doRequestAndDealData(String url) {
        new Thread(new Runnable() {
            @Override
            public void run() {

                    // 執行邏輯,請求后台json數據
                    // 直接對獲取到的數據進行處理

            }
        }).start();
    }

對比上一段代碼,我們這里直接對返回的數據進行了處理,而沒有在方法里返回數據,但是這樣的處理邏輯就是唯一的了,並不能隨着請求的url不同而執行不同的處理邏輯,那么有沒有一種方法能將在子線程中獲取到的數據"傳出去",使其能得到成功的處理呢? 這就是接口回調的巧妙之處了!

  • 先定義一個接口

public abstract class CallBackListener {

    public abstract void onFinish()

    public abstract void onError(Exception ex);

}
  • 在類A中通過在子線程發起網絡請求,並將接口作為參數,寫到類A中!

public class A {
    public void doRequest(String url,CallBackListener backListener) {
        new Thread(new Runnable() {
            @Override
            public void run() {

                try {
                    // 執行邏輯,發起網絡請求,如請求后台數據,下載文件等
                    backListener.onFinish();

                } catch (Exception ex) {
                    backListener.onError(ex);
                }
            }
        }).start();
    }
}
  • 在類B中調用類A的對象,發起請求,並且對請求得到的數據進行處理。

public class B {
    public void deal() {
        A a = new A();
        a.doRequest("http://請求的url",new CallBackListener() {
            @Override
            public void onFinish() {
                //請求成功的邏輯,如下載完成后的處理,請求到數據后的處理
            }

            @Override
            public void onError(Exception ex) {
                // 異常邏輯
            }
        });
    }
}

我們在B中調用A的方法時,重寫了接口中的方法,當發起的網絡請求完成時,就會調用我們重寫后的方法,這就是接口回調,這樣根據需要來進行不同的重寫,同樣保留了框架的意義。

我們在下載完成后,界面的點擊事件監聽,后台數據請求完成時...還有很多地方都可以用到接口回調,掌握其思想后,我們也可以寫的更加規范一點了,如將A類中的接口作參數就寫為單的一個方法,setListener(CallBackListener listener);


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM