日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Rxjava、Retrofit返回json数据解析异常处理

發(fā)布時間:2025/3/20 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Rxjava、Retrofit返回json数据解析异常处理 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

每個App都避免不了要進行網(wǎng)絡(luò)請求,從最開始的用谷歌封裝的volley到再到android-async-http再到OKHttpUtils再到現(xiàn)在的Retrofit和RxJava,從我自己用后的體驗來看,用了retrofit和RxJava真的回不去了,回不去了,不去了,去了,了…(哈哈,本來還想分析下這四個的區(qū)別,網(wǎng)上這樣的文章很多,我就沒必要多添亂了-.-)。不多逼逼,下面開始正文。

1、Rxjava和Retrofit依賴導(dǎo)入:

compile 'io.reactivex:rxandroid:1.2.0' //Rxjava專門針對anroid封裝的RxAndroid compile 'io.reactivex:rxjava:1.1.5' compile 'com.squareup.retrofit2:retrofit:2.0.2' //retrofit compile 'com.squareup.retrofit2:converter-gson:2.0.2' //gson converter compile 'com.squareup.retrofit2:adapter-rxjava:2.0.2' //Retrofit專門為Rxjava封裝的適配器 compile 'com.google.code.gson:gson:2.6.2' //Gson compile 'com.squareup.okhttp3:logging-interceptor:3.1.2' //打印網(wǎng)絡(luò)請求的log日志

2、網(wǎng)絡(luò)請求基類的配置

建立一個工廠類

public class ServiceFactory {private final Gson mGsonDateFormat;public ServiceFactory(){mGsonDateFormat = new GsonBuilder().setDateFormat("yyyy-MM-dd hh:mm:ss").create();}private static class SingletonHolder{private static final ServiceFactory INSTANCE = new ServiceFactory();}public static ServiceFactory getInstance(){return SingletonHolder.INSTANCE;}public <S> S createService(Class<S> serviceClass){Retrofit retrofit = new Retrofit.Builder().baseUrl(Constant.BASE_URL) //Retrofit2 base url 必須是這種格式的:http://xxx.xxx/.client(getOkHttpClient())--------------------------添加Gson工廠變換器也就是不用管數(shù)據(jù)解析-----------------------------------.addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()).build();return retrofit.create(serviceClass);}HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {@Overridepublic void log(String message) {//打印retrofit日志Log.i("RetrofitLog","retrofitBack ======================= "+message);}});private static final long DEFAULT_TIMEOUT = 10;private OkHttpClient getOkHttpClient(){loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);//定制OkHttpOkHttpClient.Builder builder = new OkHttpClient.Builder();builder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);builder.writeTimeout(DEFAULT_TIMEOUT,TimeUnit.SECONDS);builder.addInterceptor(loggingInterceptor);//設(shè)置緩存File httpCacheDirectory = new File(SDCardUtils.getRootDirectoryPath(),"這里是你的網(wǎng)絡(luò)緩存存放的地址");builder.cache(new Cache(httpCacheDirectory,10*1024*1024));return builder.build();}}

好了 下一步 我們要建一個網(wǎng)絡(luò)請求的基類,一般網(wǎng)絡(luò)請求返回的數(shù)據(jù)最外層的根式就是 code msg result,可變的就是result,所以我們把result的類型定義為一個泛型的

public class HttpResult<T> extends BaseEntity {public int code;private boolean isSuccess;private T result;private String msg;public void setMsg(String msg) {this.msg = msg;}public T getResult() {return result;}public void setResult(T result) {this.result = result;}public boolean isSuccess() {return code == 200;}public int getCode() {return code;} }

既然我們的網(wǎng)絡(luò)請求是rxjava配合retrofit 下面就定義我們的網(wǎng)絡(luò)請求訂閱subscriber

public abstract class HttpResultSubscriber<T> extends Subscriber<HttpResult<T>> {@Overridepublic void onNext(HttpResult<T> t) {if (t.isSuccess()) {onSuccess(t.getResult());} else {_onError(t.getMsg().getCode());}}@Overridepublic void onCompleted() {}@Overridepublic void onError(Throwable e) {e.printStackTrace();//在這里做全局的錯誤處理if (e instanceof ConnectException ||e instanceof SocketTimeoutException ||e instanceof TimeoutException) {//網(wǎng)絡(luò)錯誤_onError(-9999);}}public abstract void onSuccess(T t);public abstract void _onError(int status); }

OK我們的網(wǎng)絡(luò)請求基類已經(jīng)完成啦!下面開始我們的網(wǎng)絡(luò)請求

首先我們定義一個接口(以登錄為例):

public interface LoginService {//這個例子是post為例,如果想要了解其他的網(wǎng)絡(luò)請求,請點擊文章開始出的retrofit鏈接@FormUrlEncoded@POST(Constant.LOGIN_URL) 這里是你的登錄url//可以看到我們的登錄返回的是一個Observable,它里面包含的使我們的網(wǎng)絡(luò)請求返回的實體基類,//而我們實體基類的result現(xiàn)在就是UserInfoEntityObservable<HttpResult<UserInfoEntity>> login(@Field("mobile") String phone,@Field("password") String pwd); }

現(xiàn)在開始我們的網(wǎng)絡(luò)請求啦

public void login(String phone, String pwd) {ServiceFactory.getInstance().createService(LoginService.class).login(phone,pwd).compose(TransformUtils.<HttpResult<UserInfoEntity>>defaultSchedulers()).subscribe(new HttpResultSubscriber<UserInfoEntity>() {@Overridepublic void onSuccess(UserInfoEntity userInfoEntity) {//這是網(wǎng)絡(luò)請求陳宮的回調(diào)}@Overridepublic void _onError(int status) {//這是失敗的回調(diào) 根據(jù)status做具體的操作}}); }

你以為這樣就行了 , 這樣子確實沒毛病,確實已經(jīng)妥妥的了。可是,可是,事與愿違啊!!!

3、具體解決辦法

一般情況這是我們的返回json格式:

{"code":200,"msg":"成功","result":{} }

我們剛才定義登錄接口的時候 返回的實體基類例傳入的是UserInfoEntity 這確實是沒問題的 可是你們加入登錄失敗的時候返回的json數(shù)據(jù)格式是這樣的怎么辦?

{"code":300,"msg":"成功","result":[] }

失敗的時候返回的實體又是一個數(shù)組,這樣子就會抱一個json解析異常拿不多失敗的狀態(tài)碼和提示信息

OK其實我們的網(wǎng)絡(luò)請求已經(jīng)完成90%了,剩下的就是不重要的失敗的時候回調(diào)了。

方法一:(這是在后臺兄弟好說話,而且不打人的情況下…當然這種好人,還是有的,不過這不是我們今天要講的重點)

我們可以讓后臺返回的json數(shù)據(jù)中的result永遠是個數(shù)組。

{"code":300,"msg":"成功","result":[] }

方法二:

首先給大家看一個圖片

這就是我們要下手的地方
上面我們添加的工廠變換器是導(dǎo)入的依賴 compile 'com.squareup.retrofit2:converter-gson:2.0.2' 這個提供的

那可能有人要問了,那我們不用這個用哪個啊,不著急,不著急。還好retrofit是支持自定義的ConverterFactory的

下面我們就開始我們的自定義征程吧。

1、自定義Gson響應(yīng)體變換器

public class GsonResponseBodyConverter<T> implements Converter<ResponseBody,T>{private final Gson gson;private final Type type;public GsonResponseBodyConverter(Gson gson,Type type){this.gson = gson;this.type = type;}@Overridepublic T convert(ResponseBody value) throws IOException {String response = value.string();//先將返回的json數(shù)據(jù)解析到Response中,如果code==200,則解析到我們的實體基類中,否則拋異常Response httpResult = gson.fromJson(response, Response.class);if (httpResult.getCode()==200){//200的時候就直接解析,不可能出現(xiàn)解析異常。因為我們實體基類中傳入的泛型,就是數(shù)據(jù)成功時候的格式return gson.fromJson(response,type);}else {ErrorResponse errorResponse = gson.fromJson(response,ErrorResponse.class);//拋一個自定義ResultException 傳入失敗時候的狀態(tài)碼,和信息throw new ResultException(errorResponse.getCode(),errorResponse.getMsg());}} }

2、自定義一個響應(yīng)變換工廠 繼承自 retrofit的 converter.Factory

public class ResponseConverterFactory extends Converter.Factory {public static ResponseConverterFactory create() {return create(new Gson());}public static ResponseConverterFactory create(Gson gson) {return new ResponseConverterFactory(gson);}private final Gson gson;private ResponseConverterFactory(Gson gson) {if (gson == null) throw new NullPointerException("gson == null");this.gson = gson;}@Overridepublic Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {//返回我們自定義的Gson響應(yīng)體變換器return new GsonResponseBodyConverter<>(gson, type);}@Overridepublic Converter<?, RequestBody> requestBodyConverter(Type type,Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {//返回我們自定義的Gson響應(yīng)體變換器return new GsonResponseBodyConverter<>(gson,type);} } 然后將上面的GsonConverterFactory.create() 替換成我們自定義的ResponseConverterFactory.create()。public <S> S createService(Class<S> serviceClass){Retrofit retrofit = new Retrofit.Builder().baseUrl(Constant.BASE_URL).client(getOkHttpClient())//.addConverterFactory(GsonConverterFactory.create())//然后將上面的GsonConverterFactory.create()替換成我們自定義的ResponseConverterFactory.create().addConverterFactory(ResponseConverterFactory.create()).addCallAdapterFactory(RxJavaCallAdapterFactory.create()).build();return retrofit.create(serviceClass);}

再然后,最后一個然后啦(-.-)

在我們的自定義的Rxjava訂閱者 subscriber中的onError()中加入我們剛才定義的ResultException。

@Override public void onError(Throwable e) {e.printStackTrace();//在這里做全局的錯誤處理if (e instanceof ConnectException ||e instanceof SocketTimeoutException ||e instanceof TimeoutException) {//網(wǎng)絡(luò)錯誤_onError(-9999);} else if (e instanceof ResultException) {//自定義的ResultException//由于返回200,300返回格式不統(tǒng)一的問題,自定義GsonResponseBodyConverter凡是300的直接拋異常_onError(((ResultException) e).getErrCode());System.out.println("---------errorCode------->"+((ResultException) e).getErrCode());} }

這次是真的完成了我們的json數(shù)據(jù)解析異常的處理,其實我們的解決辦法是解析了兩次,第一次解析的時候我們的Response中只有只是解析了最外層的 code 和 msg ,result中的是沒有解析的。response中的code==200,直接將數(shù)據(jù)解析到我們的實體基類中。如果code!=200時,直接拋自定義的異常,直接會回調(diào)到subscriber中的onError()中。雖然進行了兩次解析,但是第一次只是解析了code,和msg 對于效率的影響其實并不大,在功能實現(xiàn)的基礎(chǔ)上一點點效率的影響(而且這個影響是微乎其微的-.-)其實無傷大雅的。

原文發(fā)布時間為:2018-07-11
本文來自云棲社區(qū)合作伙伴“安卓巴士Android開發(fā)者門戶”,了解相關(guān)信息可以關(guān)注“安卓巴士Android開發(fā)者門戶”。

總結(jié)

以上是生活随笔為你收集整理的Rxjava、Retrofit返回json数据解析异常处理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 中国精品久久 | 亚洲精品乱码久久久久久黑人 | 久久男人精品 | 在线h网站| 好色av | 越南黄色一级片 | 桃色视频网 | 日本边添边摸边做边爱 | 中文字幕无码精品亚洲 | 一区二区在线观看av | 中国黄色大片 | 伊人99热| 狠狠操女人 | 99视频网站 | 69性视频| 成年人在线免费观看网站 | 亚洲欧美在线不卡 | 国产女主播视频 | 久久久二区 | 欧美激情视频在线播放 | 欧美成人精品一区二区三区 | 三年电影在线观看 | 欧美激情在线看 | 欧美做受xxxxxⅹ性视频 | 美女扒开屁股让男人桶 | 日韩一区二区三区在线看 | 艹少妇视频 | 97超碰人人 | 欧美区二区三区 | 国产成人一区二区 | 美日韩黄色片 | 欧美成人看片黄a免费看 | 伊人网在线视频观看 | 青青草视频在线免费观看 | www久久com | 久久精品欧美一区二区三区麻豆 | 激情av在线| 精品人妻码一区二区三区红楼视频 | 欧美日韩免费一区二区三区 | 久久人人爽人人爽人人片av免费 | 91精品国产综合久久精品图片 | 麻豆91视频| 亚洲国产欧美精品 | 国产欧美另类 | 日本高清视频在线播放 | 亚洲大尺度视频 | 日韩精品视频一区二区 | 欧美国产日韩视频 | 女同久久另类69精品国产 | 91国偷自产一区二区三区观看 | 亚洲精品乱码久久久久久蜜桃欧美 | 国产精品久久久久aaaa | 国产欧美一区二区三区在线老狼 | 四虎视频 | 99国产视频 | 精品一区二区日韩 | 97干视频| 人人妻人人澡人人爽人人精品 | 永久免费在线播放 | 国产夫妻性爱视频 | 成年人免费看的视频 | 贵族女沦为官妓h呻吟 | 精品国产1区2区 | 国产美女网站视频 | 人妻在卧室被老板疯狂进入 | 亚洲最大福利视频 | 波多野结衣操 | 亚洲国产成人精品一区二区三区 | 人妻丰满熟妇av无码久久洗澡 | 制服丝袜一区在线 | 美女羞羞动态图 | 人妻熟女一区二区三区app下载 | 天天色天天干天天色 | 一级黄色片在线播放 | 免费的黄色一级片 | 色婷婷九月| 91亚洲欧美激情 | 男女毛片视频 | 在线第一页 | 反差在线观看免费版全集完整版 | 91爱爱视频 | 色综合福利 | 6080毛片 | av成人资源| 邻居校草天天肉我h1v1 | 大地资源二中文在线影视免费观看 | 欧美在线一二三四区 | 欧美永久 | 国产丝袜美腿一区二区三区 | 91黄色免费版 | 丁香激情婷婷 | 亚洲免费看片 | 中文字幕超清在线观看 | 两性囗交做爰视频 | 在线观看国产欧美 | 国产jjizz一区二区三区视频 | 久久er99热精品一区二区介绍 | 一级大片视频 | 91蝌蚪少妇偷拍 |