版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、Retrofit+RxJava 優(yōu)雅的處理服務(wù)器返回異常、錯(cuò)誤異常&錯(cuò)誤實(shí)際開發(fā)經(jīng)常有這種情況,比如登錄請(qǐng)求,接口返回的 信息包括請(qǐng)求返回的狀態(tài):失敗還是成功,錯(cuò)誤碼,User對(duì)象等等。如果網(wǎng)絡(luò)等原因引起的登錄失敗可以歸結(jié)為異常,如果是用戶信息輸入錯(cuò)誤導(dǎo)致的登錄失敗算是錯(cuò)誤。假如服務(wù)器返回的是統(tǒng)一數(shù)據(jù)格式:/* * 標(biāo)準(zhǔn)數(shù)據(jù)格式 * param <T> */public class Response<T> public int state; public String message; public T data;網(wǎng)絡(luò)異常導(dǎo)致的登錄失敗,在使用Retrofit+
2、RxJava請(qǐng)求時(shí)都會(huì)直接調(diào)用subscribe的onError事件;密碼錯(cuò)誤導(dǎo)致的登錄失敗,在使用Retrofit+RxJava請(qǐng)求時(shí)都會(huì)調(diào)用subscribe的onNext事件;無(wú)論是異常還是錯(cuò)誤,都要在subscribe里面處理異常信息,如下代碼:APIWrapper.getInstance().login("username", "password") .subscribe(new Observer<Response<User>>() Override public void onCompleted() Override
3、public void onError(Throwable e) Override public void onNext(Response<User> data) if(data.state = 1001) /. else if(data.state = 1002) );現(xiàn)在我希望在發(fā)生任何錯(cuò)誤的情況下,都會(huì)調(diào)用onError事件,并且由model來(lái)處理錯(cuò)誤信息。那么,此時(shí)我們就應(yīng)該有一個(gè)ExceptionEngine來(lái)處理事件流中的錯(cuò)誤信息了。在工作流中處理異常在正常情況下,我們獲取網(wǎng)絡(luò)數(shù)據(jù)的流程通常如下:請(qǐng)求接口->解析數(shù)據(jù)->更新整個(gè)數(shù)據(jù)請(qǐng)求過程都是發(fā)生在Rx中的
4、工作流之中。當(dāng)有異常產(chǎn)生的時(shí)候,我們要盡量不在ui層里面進(jìn)行判斷,換句話說,我們沒有必要去告訴ui層具體的錯(cuò)誤信息,只需要讓他彈出一個(gè)信息(Toast或者Dialog)展示我們給它的信息就行。請(qǐng)求接口和數(shù)據(jù)解析都可能出錯(cuò),所以在這兩層進(jìn)行錯(cuò)誤處理。為了更好的解耦,我們通過攔截器攔截錯(cuò)誤,然后根據(jù)錯(cuò)誤類型分發(fā)信息。攔截器數(shù)據(jù)解析層的攔截器這個(gè)攔截器主要是為了獲取具體的錯(cuò)誤信息,分發(fā)給上層的UI,給用戶以提示,增強(qiáng)用戶體驗(yàn)。public Observable<Weather> getWeather(String cityName) return weatherService.getWe
5、ather(cityName) /攔截服務(wù)器返回的錯(cuò)誤 .map(new ServerResponseFunc<Weather>() /HttpResultFunc()為攔截onError事件的攔截器,后面會(huì)講到,這里先忽略 .onErrorResumeNext(new HttpResponseFunc<Weather>(); /攔截固定格式的公共數(shù)據(jù)類型Response<T>,判斷里面的狀態(tài)碼private class ServerResponseFunc<T> implements Func1<Response<T>, T&
6、gt; Override public T call(Response<T> reponse) /對(duì)返回碼進(jìn)行判斷,如果不是0,則證明服務(wù)器端返回錯(cuò)誤信息了,便根據(jù)跟服務(wù)器約定好的錯(cuò)誤碼去解析異常 if (reponse.state != 0) /如果服務(wù)器端有錯(cuò)誤信息返回,那么拋出異常,讓下面的方法去捕獲異常做統(tǒng)一處理 throw new ServerException(reponse.state,reponse.message); /服務(wù)器請(qǐng)求數(shù)據(jù)成功,返回里面的數(shù)據(jù)實(shí)體 return reponse.data; 所以整個(gè)邏輯是這樣的: 所以在前三步的過程中,只要發(fā)生異常(服務(wù)
7、器返回的錯(cuò)誤也拋出了)都會(huì)拋出,這時(shí)候就觸發(fā)了RxJava的OnError事件。處理onError事件的攔截器這個(gè)攔截器主要是將異常信息轉(zhuǎn)化為用戶”能看懂”的友好提示。 private class HttpResponseFunc<T> implements Func1<Throwable, Observable<T>> Override public Observable<T> call(Throwable throwable) /ExceptionEngine為處理異常的驅(qū)動(dòng)器 return Observable.error(Exceptio
8、nEngine.handleException(throwable); 兩個(gè)攔截器以前使用,代碼如下:public Observable<Weather> getWeather(String cityName) return weatherService.getWeather(cityName) /攔截服務(wù)器返回的錯(cuò)誤 .map(new ServerResponseFunc<Weather>() /HttpResponseFunc()為攔截onError事件的攔截器 .onErrorResumeNext(new HttpResponseFunc<Weather&g
9、t;(); 調(diào)用:APIWrapper.getInstance().getWeather("北京") .subscribe(new SampleProgressObserver<Weather>(MainActivity.this) Override public void onNext(WeatherBean weatherBean) tv.setText(weatherBean.toString(); );相關(guān)類:public class RxSubscriber<T> extends ErrorSubscriber<T> Overr
10、ide public void onStart() super.onStart(); DialogHelper.showProgressDlg(context, "正在加載數(shù)據(jù)"); Override public void onCompleted() DialogHelper.stopProgressDlg(); Override protected void onError(ApiException ex) DialogHelper.stopProgressDlg(); Toast.makeText(context, ex.message, Toast.LENGTH_S
11、HORT).show(); Override public void onNext(T t) public abstract class ErrorSubscriber<T> extends Observer<T> Override public void onError(Throwable e) if(e instanceof ApiException) onError(ApiException)e); else onError(new ApiException(e,123); /* * 錯(cuò)誤回調(diào) */ protected abstract void onError(
12、ApiException ex);處理異常的驅(qū)動(dòng)器package ;import .ParseException;import com.google.gson.JsonParseException;import org.json.JSONException;import .ConnectException;import retrofit2.adapter.rxjava.HttpException;/* * Created by Lzx on 2016/7/11. */public class ExceptionEngine /對(duì)應(yīng)HTTP的狀態(tài)碼 private static final in
13、t UNAUTHORIZED = 401; private static final int FORBIDDEN = 403; private static final int NOT_FOUND = 404; private static final int REQUEST_TIMEOUT = 408; private static final int INTERNAL_SERVER_ERROR = 500; private static final int BAD_GATEWAY = 502; private static final int SERVICE_UNAVAILABLE = 5
14、03; private static final int GATEWAY_TIMEOUT = 504; public static ApiException handleException(Throwable e) ApiException ex; if (e instanceof HttpException) /HTTP錯(cuò)誤 HttpException httpException = (HttpException) e; ex = new ApiException(e, ERROR.HTTP_ERROR); switch(httpException.code() case UNAUTHORI
15、ZED: case FORBIDDEN: case NOT_FOUND: case REQUEST_TIMEOUT: case GATEWAY_TIMEOUT: case INTERNAL_SERVER_ERROR: case BAD_GATEWAY: case SERVICE_UNAVAILABLE: default: ex.message = "網(wǎng)絡(luò)錯(cuò)誤" /均視為網(wǎng)絡(luò)錯(cuò)誤 break; return ex; else if (e instanceof ServerException) /服務(wù)器返回的錯(cuò)誤 ServerException resultException
16、= (ServerException) e; ex = new ApiException(resultException, resultException.code); ex.message = resultException.message; return ex; else if (e instanceof JsonParseException | e instanceof JSONException | e instanceof ParseException) ex = new ApiException(e, ERROR.PARSE_ERROR); ex.message = "解
17、析錯(cuò)誤" /均視為解析錯(cuò)誤 return ex; else if(e instanceof ConnectException) ex = new ApiException(e, ERROR.NETWORD_ERROR); ex.message = "連接失敗" /均視為網(wǎng)絡(luò)錯(cuò)誤 return ex; else ex = new ApiException(e, ERROR.UNKNOWN); ex.message = "未知錯(cuò)誤" /未知錯(cuò)誤 return ex; /* * 約定異常 */public class ERROR /* * 未知錯(cuò)誤
18、*/ public static final int UNKNOWN = 1000; /* * 解析錯(cuò)誤 */ public static final int PARSE_ERROR = 1001; /* * 網(wǎng)絡(luò)錯(cuò)誤 */ public static final int NETWORD_ERROR = 1002; /* * 協(xié)議出錯(cuò) */ public static final int HTTP_ERROR = 1003;public class ApiException extends Exception public int code; public String message; pu
19、blic ApiException(Throwable throwable, int code) super(throwable); this.code = code; public class ServerException extends RuntimeException public int code; public String message;DialogHelper.Javapublic class DialogHelper /* * 通用Dialog * */ / 因?yàn)楸绢惒皇莂ctivity所以通過繼承接口的方法獲取到點(diǎn)擊的事件 public interface OnOkCli
20、ckListener abstract void onOkClick(); /* * Listener */ public interface OnCancelClickListener abstract void onCancelClick(); private static AlertDialog mDialog; public static void showDialog(Context context, String title, String content, final OnOkClickListener listenerYes, final OnCancelClickListen
21、er listenerNo) showDialog(context, context.getString(android.R.string.ok), context.getString(android.R.string.cancel), title, content, listenerYes, listenerNo); public static void showDialog(Context context, String ok, String cancel, String title, String content, final OnOkClickListener listenerYes,
22、 final OnCancelClickListener listenerNo) AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setMessage(content); / 設(shè)置title builder.setTitle(title); / 設(shè)置確定按鈕,固定用法聲明一個(gè)按鈕用這個(gè)setPositiveButton builder.setPositiveButton(ok, new DialogInterface.OnClickListener() public void onClick(Dia
23、logInterface dialog, int which) / 如果確定被電擊 if (listenerYes != null) listenerYes.onOkClick(); mDialog = null; ); / 設(shè)置取消按鈕,固定用法聲明第二個(gè)按鈕要用setNegativeButton builder.setNegativeButton(cancel, new DialogInterface.OnClickListener() public void onClick(DialogInterface dialog, int which) / 如果取消被點(diǎn)擊 if (listener
24、No != null) listenerNo.onCancelClick(); mDialog = null; ); / 控制這個(gè)dialog可不可以按返回鍵,true為可以,false為不可以 builder.setCancelable(false); / 顯示dialog mDialog = builder.create(); if (!mDialog.isShowing() mDialog.show(); public static void showDialog(Context context, int ok, int cancel, int title, int content, f
25、inal OnOkClickListener listenerYes, final OnCancelClickListener listenerNo) showDialog(context, context.getString(ok), context.getString(cancel), context.getString(title), context.getString(content), listenerYes, listenerNo); static ProgressDialog progressDlg = null; /* * 啟動(dòng)進(jìn)度條 * * param strMessage
26、進(jìn)度條顯示的信息 * param / 當(dāng)前的activity */ public static void showProgressDlg(Context ctx, String strMessage) if (null = progressDlg) if (ctx = null) return; progressDlg = new ProgressDialog(ctx); /設(shè)置進(jìn)度條樣式 progressDlg.setProgressStyle(ProgressDialog.STYLE_SPINNER); /提示的消息 progressDlg.setMessage(strMessage);
27、progressDlg.setIndeterminate(false); progressDlg.setCancelable(true); progressDlg.show(); public static void showProgressDlg(Context ctx) showProgressDlg(ctx, ""); /* * 結(jié)束進(jìn)度條 */ public static void stopProgressDlg() if (null != progressDlg && progressDlg.isShowing() progressDlg.dism
28、iss(); progressDlg = null; if (null != dialog && dialog.isShowing() dialog.dismiss(); dialog = null; private static Dialog dialog; public static void showDialogForLoading(Context context, String msg, boolean cancelable) if (null = dialog) if (null = context) return; View view = LayoutInflate
29、r.from(context).inflate(R.layout.layout_loading_dialog, null); TextView loadingText = (TextView)view.findViewById(R.id.loading_tip_text); loadingText.setText(msg); dialog = new Dialog(context, R.style.loading_dialog_style); dialog.setCancelable(cancelable); dialog.setCanceledOnTouchOutside(cancelabl
30、e); dialog.setContentView(iew, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); Activity activity = (Activity) context; if (activity.isFinishing() return; dialog.show(); 可能本博客也不是最好的解決方案,如果有更好的想法,我愿與你互相交流!分享: Retrofit+RxJava錯(cuò)誤預(yù)處理看到bobo_wan
31、g的文章,不僅感覺有受益匪淺,這里做下介紹。首先定義如下Transformer轉(zhuǎn)換器。public static <T> Observable.Transformer<Response<T>, T> sTransformer() return responseObservable -> responseObservable.map(tResponse -> if (!tResponse.success) throw new RuntimeException(tResponse.code); return tRata; ).onErrorResum
32、eNext(new HttpResponseFunc<>(); public static <T> Observable.Transformer<T, T> switchSchedulers() return observable -> observable.subscribeOn(Schedulers.io() .observeOn(AndroidSchedulers.mainThread(); private static class HttpResponseFunc<T> implements Func1<Throwable,
33、Observable<T>> Override public Observable<T> call(Throwable throwable) /ExceptionEngine為處理異常的驅(qū)動(dòng)器 return Observable.error(new Throwable(throwable); 調(diào)用:public void login(View v) apiservice.login(name,pwd) .compose(Transformers.sTransformer() .compose(Transformers.switchSchedulers() .sub
34、scribe(subscriber);private Subscriber<UserModel> subscriber = new Subscriber<UserModel>() Override public void onCompleted() / do onCompleted Override public void onError(Throwable e) / do on success != true; / do on http error / do on other error Override public void onNext(UserModel mo
35、del) / parse data ;接口:FormUrlEncoded POST("interface?login")Observable<Response<UserModel>> login(Field("name") String name,Field("pwd") String pwd);最后再來(lái)點(diǎn)干貨。Transformer 和 Func 處理的區(qū)別如上的處理,定義了 一個(gè) sTransformer 和一個(gè) HttpResponseFunc, 從中可以明顯感覺的到sTransformer其實(shí)也是可以用
36、Func1來(lái)定義的,public void login(View v) apiservice.login(name,pwd) .compose(Transformers.switchSchedulers() .map(new TransFuc<UserModel>() .onErrorReturn(new HttpResponseFunc<>() .subscribe(subscriber);public static class TransFuc<T> implements Func1<Response<T>, T> Override public T call(Response<T> tResponse) if (!tResponse.success) throw new RuntimeException(tResponse.code); return tRe
溫馨提示
- 1. 本站所有資源如無(wú)特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 廣東理工學(xué)院《蔬菜栽培學(xué)總論》2023-2024學(xué)年第一學(xué)期期末試卷
- 廣東科技學(xué)院《珠寶玉石概論》2023-2024學(xué)年第一學(xué)期期末試卷
- 廣東江門幼兒師范高等專科學(xué)?!吨兴幏治觥?023-2024學(xué)年第一學(xué)期期末試卷
- 廣東工業(yè)大學(xué)《現(xiàn)代儀器分析技術(shù)》2023-2024學(xué)年第一學(xué)期期末試卷
- 《吉蘭巴雷的護(hù)理》課件
- 課間安全教學(xué)課件
- 廣安職業(yè)技術(shù)學(xué)院《民法婚姻家庭與繼承編》2023-2024學(xué)年第一學(xué)期期末試卷
- 共青科技職業(yè)學(xué)院《報(bào)關(guān)實(shí)訓(xùn)》2023-2024學(xué)年第一學(xué)期期末試卷
- 贛州職業(yè)技術(shù)學(xué)院《技術(shù)軟件應(yīng)用》2023-2024學(xué)年第一學(xué)期期末試卷
- 贛南醫(yī)學(xué)院《通風(fēng)工程課程設(shè)計(jì)》2023-2024學(xué)年第一學(xué)期期末試卷
- 數(shù)據(jù)中心電力設(shè)備調(diào)試方案
- 2024年度國(guó)際物流運(yùn)輸合同3篇
- 新入職員工年終工作總結(jié)課件
- 中華傳統(tǒng)文化之文學(xué)瑰寶學(xué)習(xí)通超星期末考試答案章節(jié)答案2024年
- 靜脈導(dǎo)管維護(hù)
- 年度先進(jìn)員工選票標(biāo)準(zhǔn)格式
- 《錄音技術(shù)與藝術(shù)》課程教學(xué)大綱(新版)(共11頁(yè))
- OBC測(cè)試報(bào)告模板
- 性病診斷標(biāo)準(zhǔn)與報(bào)病要求
- 國(guó)營(yíng)農(nóng)場(chǎng)隊(duì)長(zhǎng)崗位職責(zé)(精選5篇)_農(nóng)場(chǎng)場(chǎng)長(zhǎng)崗位職責(zé)
- 工程作業(yè)活動(dòng)風(fēng)險(xiǎn)評(píng)價(jià)記錄表及分級(jí)管控清單【全面】
評(píng)論
0/150
提交評(píng)論