在使用接口回調的時候發現了一個常常犯的錯誤,就是回調函數裏面的實現有多是用多線程或者是異步任務去作的,這就會致使咱們指望函數回調完畢去返 回一個主函數的結果,實際發現是行不通的,由於若是回調是多線程的話你是沒法和主函數同步的,也就是返回的數據是錯誤的,這是很是隱祕的一個錯誤。那有什 麼好的方法去實現數據的線性傳遞呢?先介紹下回調機制原理。編程
回調函數json
回調函數就是一個經過函數指針調用的函數。若是你把函數的指針(地址)做爲參數傳遞給另外一個函數,當這個指針被用爲調用它所指向的函數時,咱們就說 這是回調函數。回調函數不是由該函數的實現方直接調用,而是在特定的事件或條件發生時由另外的一方調用的,用於對該事件或條件進行響應。服務器
詳細解釋:
客戶程序C調用服務程序S中的某個函數A,而後S又在某個時候反過來調用C中的某個函數B,對於C來講,這個B便叫作回調函數。例如Win32下的窗 口過程函數就是一個典型的回調函數。通常說來,C不會本身調用B,C提供B的目的就是讓S來調用它,並且是C不得不提供。因爲S並不知道C提供的B姓甚名 誰,因此S會約定B的接口規範(函數原型),而後由C提早經過S的一個函數R告訴S本身將要使用B函數,這個過程稱爲回調函數的註冊,R稱爲註冊函數。 Web Service以及Java的RMI都用到回調機制,能夠訪問遠程服務器程序。
下面舉個通俗的例子:
某天,我打電話向你請教問題,固然是個難題,你一時想不出解決方法,我又不能拿着電話在那裏傻等,因而咱們約定:等你想出辦法後打手機通知我,這樣, 我就掛掉電話辦其它事情去了。過了XX分鐘,個人手機響了,你興高采烈的說問題已經搞定,應該如此這般處理。故事到此結束。這個例子說明了「異步+回調」 的編程模式。其中,你後來打手機告訴我結果即是一個「回調」過程;個人手機號碼必須在之前告訴你,這即是註冊回調函數;個人手機號碼應該有效而且手機可以接收到你的呼叫,這是回調函數必須符合接口規範。
JAVA中不容許直接操做指針,那它的回調是如何實現的呢?
答案:它是經過接口或者內部類來實現的。
JAVA方法回調是功能定義和功能實現分享的一種手段,是一種耦合設計思想。做爲一種架構,必須有本身的運行環境,而且提供用戶的實現接口。
1. 定義接口 Callback ,包含回調方法 callback()
2. 在一個類Caller 中聲明一個Callback接口對象 mCallback
3. 在程序中賦予 Caller對象的接口成員(mCallback) 一個內部類對象如
new Callback(){
callback(){
//函數的具體實現
}
}
多線程
這樣,在須要的時候,可用Caller對象的mCallback接口成員 調用callback()方法,完成回調。架構
回調機制在Android框架中的使用框架
在Activity中定義了不少生命週期的不一樣狀態要調用的方法,這些方法都是空實現,系統框架要調用,用戶也要調用來實現。
實例(對於Android界面上Button點擊事件監聽的模擬):
a.定義接口
public interface OnClickListener {
public void OnClick(Button b);
b. 定義Button
public class Button {
OnClickListener listener;
public void click() {
listener.OnClick(this);
}
public void setOnClickListener(OnClickListener listener) {
this.listener = listener;
}
}
c. 將接口對象OnClickListener 賦給 Button的接口成員
public class Activity {
public Activity() {
}
public static void main(String[] args) {
Button button = new Button();
button.setOnClickListener(new OnClickListener(){
@Override
public void OnClick(Button b) {
System.out.println(clicked);
}
});
button.click(); //user click,System call button.click();
}
}異步
機制原理如上,那數據傳遞依靠接口怎麼傳遞呢?上代碼:ide
1函數 2this 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
/* * @author sunglasses * @category 利用xUtils框架封裝get方法,IOAuthCallBack是數據接口回調,send方法裏面 有異步任務方法, * 傳統返回數據方法可能返回數據不正確。 */ publicclassxUtilsGet {
publicvoidgetJson(String url,RequestParams params,finalIOAuthCallBack iOAuthCallBack){
HttpUtils http =newHttpUtils(); http.configCurrentHttpCacheExpiry(1000*10); http.send(HttpMethod.GET, url, params,newRequestCallBack<string>() {
@Override publicvoidonFailure(HttpException arg0, String arg1) { // TODO Auto-generated method stub }
@Override publicvoidonSuccess(ResponseInfo<string> info) { // TODO Auto-generated method stub iOAuthCallBack.getIOAuthCallBack(info.result); } }); }}</string></string> |
我用的是xUtils開發框架而後返回數據的時候用的是接口回調,接口定義以下:
1 2 3 |
publicinterfaceIOAuthCallBack { publicvoidgetIOAuthCallBack(String result); } |
上層函數定義以下:
1 2 3 4 5 6 |
publicvoidgetCataJson(intcityId,IOAuthCallBack iOAuthCallBack) { String url = http://xxxxxxx; RequestParams params =newRequestParams(); params.addQueryStringParameter(currentCityId, cityId+); getJson(url,params,iOAuthCallBack); } |
getcatajson是在你想獲得數據的類中調用,而後傳入參數和接口對象,接口對象中是要對最終數據進行處理。具體機制原理如上。這樣就能夠避免接口回調中的多線程數據不一致問題。