Retrofit網路異常回調中拿到網路請求url等資料
前言
開心原創哦
Retrofit 與RxJava結合,異常 處理都走了onError(Throwable t) 方法. 在該異常回調中,我們拿不到網路請求url等資料,只能拿到Throwable物件。
使用場景
異常統一處理,但異常回調中無法區分哪一個介面網路請求出現異常了。例如一個介面有多個介面,其中某個介面請求出現異常了,在異常統一處理裡面無法區分。(使用場景):介面A有 下拉重新整理和 上拉載入的介面, 同時還有點贊 、關注介面,當在上拉載入更多過程中,點贊介面觸發,若某一介面請求失敗,無法區分是上拉加載出現異常,還是點贊失敗,這對於處理對應的UI是無法完成的。
解決方法一: 在不同接口裡面傳入對應的new Action<Throwable>, 這 樣每個介面單獨處理 自己的異常回調
解決方法二: 在異常處理的回撥中拿到對應介面的資料,如url等,這樣就可以區分是哪個介面網路請求異常了。
方法一大家一般都知道如何使用,我就不作累述了。
在Rxjava 的onError回撥中拿到網路請求的URL等資料
在建立Retrofit物件時,會傳入CallAdapter.Factory 物件,該物件是專門處理回撥的。包括成功、失敗回撥。
如下:
new Retrofit.Builder().addCallAdapterFactory(RxJavaCallAdapterFactory.create());
因為使用Rxjava與Retrofit結合,所以這裡添加回調是使用RxJavaCallAdapterFactory建立的。
由於每一個版本的Retrofit的原始碼都略有不一樣,但原理相同,大家可以根據我的思路去解決。我司的專案依賴的2.1.0版本
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
查看了RxJavaCallAdapterFactory的原始碼,Retrofit與Rxjava結合使用時,回撥處理都交給了這個庫來作處理,將Retrofit丟擲的異常給Rxjava的onError回撥,將請求成功給onNext和onComplete
'com.squareup.retrofit2:adapter-rxjava:2.1.0
通過debug可以發現所有回撥最後都走了RxJavaCallAdapterFactory 裡面的這個方法。
@Override
public void request(long n) {
if (n < 0) throw new IllegalArgumentException("n < 0: " + n);
if (n == 0) return; // Nothing to do when requesting 0.
if (!compareAndSet(false, true)) return; // Request was already triggered.
try {
Response<T> response = call.execute();
if (!subscriber.isUnsubscribed()) {
subscriber.onNext(response);
}
} catch (Throwable t) {
Exceptions.throwIfFatal(t);
if (!subscriber.isUnsubscribed()) {
// MyNetThrowable myNetThrowable = new MyNetThrowable(t, call);
subscriber.onError(t);
}
return;
}
if (!subscriber.isUnsubscribed()) {
subscriber.onCompleted();
}
}
為了在onError回撥中拿到網路url等資料,在這裡我們可以 自定義一個Throwable,然後將網路的Call物件放進去,這樣通過Call物件就可以 拿到請求url, host,headers,請求引數等資料了。
自主 義Throwable物件 MyNetThrowable,如下:
public class MyNetThrowable extends Throwable {
public final Call call;
public MyNetThrowable(Throwable e, Call call) {
super(e);
this.call = call;
}
public Call getCall() {
return call;
}
}
然後修改RxJavaCallAdapterFactory的原始碼 即可。請注意上面註釋的那一行程式碼,
if (!subscriber.isUnsubscribed()) {
MyNetThrowable myNetThrowable = new MyNetThrowable(t, call);
subscriber.onError(myNetThrowable);
}
這樣既可以拿到之前的Throwable物件,也可以拿到請求Call物件
使用:
在onError回撥方法中,mError是給Rxjava的onError回撥使用的,所有網路請求異常都會走這裡。
protected final Action1<Throwable> mError = t -> {
if (t instanceof MyNetThrowable) {
MyNetThrowable t1 = (MyNetThrowable) t;
Call call = t1.call;
Request request = call.request();
Headers headers = request.headers();
HttpUrl url = request.url();
URL url1 = url.url();
}
}
這樣就可以知道哪一個介面網路請求出現異常了。
延伸
如何修改RxJavaCallAdapterFactory原始碼,如何自定義CallAdapterFactory、
檢視其原始碼可以發現RxJavaCallAdapterFactory是 不允許你對其自定義的,需要修改其原始碼打成jar包重新依賴。
備註: 2.1.0版本的是這個情況,現最新版本已經更新了,RxJavaCallAdapterFactory 的原始碼也更改頗多,但原理沒變,大家可以關注一下最新版本。
先從retrofit 的github網址上下載對應版本號的原始碼,然後做成android lib ,修改完成後打成aar包,將aar包中jar包複製出來放入專案的lib資料夾即可(該lib除了程式碼沒有其它資源,直接複製其jar包即可了,依賴也方便),不再使用如下方式依賴了。
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
如下圖