Rtrofit+Rxjava網絡請求封裝

好幾年前封裝的框架一直沒上傳,趁現在升級寫下。

? ? ?簡介Retrofit是android的網絡請求庫,是一個RESTful的HTTP網絡請求框架的封裝(基于okhttp)。它內部網絡請求的工作,本質上是通過OkHttp完成,而Retrofit僅負責網絡請求接口的封裝。

目錄

一、引包

二、網絡請求分為三個包分別為data、httptool、request三個pakage包。

三、pakage包分析

? ? ? ?3.1.data

? ? ? ? ? ? ? 3.1.1HttpBaseResponse

? ?3.1.2.HttpDisposable

????????3.1.3.HttpResponseInterface

3.2.httptool 為http工具類的封裝

? ? 3.2.1 添加cookie攔截

? 3.2.2.HttpException自定義異常拋出

? 3.2.3?HttpInterceptor請求攔截器

3.2.4.ResponseConverterFactory處理服務器返回數據將數據轉換成對象

?3.2.5?UploadUtils 文件上傳

3.3 request

3.3.1.ApiAddress網絡請求接口地址

3.3.2.HttpFactory網絡請求

3.3.3HttpRequest

3.3.4ServerAddress

四、使用

4.1.在應用的applacation中初始化

4.2.請求示例


一、引包

    //    retrofit2implementation 'com.squareup.retrofit2:retrofit:2.4.0'implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'implementation 'com.squareup.retrofit2:converter-gson:2.4.0'//    RxJavaimplementation 'io.reactivex.rxjava2:rxandroid:2.0.2'implementation 'io.reactivex.rxjava2:rxjava:2.1.12'

二、網絡請求分為三個包分別為data、httptool、request三個pakage包。

? ? ??data:數據處理封裝類

? ? ??httptool:網絡請求工具

? ? ? request:請求處理

三、pakage包分析

? ? ? ?3.1.data

? ? ? ? ? ? ? data中有三個對象,分別對應? HttpBaseResponse(http響應處理)、HttpDisposable(與rxjava請求回調處理)、HttpResponseInterface(獲取處理掉code和msg后的信息)。

? ? ? ? ? ? ? 3.1.1HttpBaseResponse

/*** @author shizhiyin*/
public interface HttpResponseInterface {/*** 獲取處理掉code和msg后的信息** @param gson* @param response* @return*/String getResponseData(Gson gson, String response);}

? ?3.1.2.HttpDisposable


/*** @author shizhiyin* 返回數據*/
public abstract class HttpDisposable<T> extends DisposableObserver<T> {public HttpDisposable() {}@Overrideprotected void onStart() {}@Overridepublic void onNext(T value) {success(value);}@Overridepublic void onError(Throwable e) {}@Overridepublic void onComplete() {}public abstract void success(T t);
}

????????3.1.3.HttpResponseInterface

/*** @author shizhiyin*/
public interface HttpResponseInterface {/*** 獲取處理掉code和msg后的信息** @param gson* @param response* @return*/String getResponseData(Gson gson, String response);}

3.2.httptool 為http工具類的封裝

? ? 3.2.1 添加cookie攔截


public class AddCookiesInterceptor implements Interceptor {@Overridepublic Response intercept(Chain chain) throws IOException {if (!NetworkUtils.isConnected()) {throw new HttpException("網絡連接異常,請檢查網絡后重試");}Request.Builder builder = chain.request().newBuilder();HashSet<String> preferences = Hawk.get(Constants.HawkCode.COOKIE);if (preferences != null) {for (String cookie : preferences) {builder.addHeader("Cookie", cookie);Log.v("OkHttp", "Adding Header: " + cookie);// This is done so I know which headers are being added; this interceptor is used after the normal logging of OkHttp}}return chain.proceed(builder.build());}
}

? 3.2.2.HttpException自定義異常拋出

? ??


/*** 自定義異常拋出** @author shizhiyin*/
public class HttpException extends RuntimeException {public HttpException(String message) {this.message = message;}public HttpException(int code, String message) {this.message = message;this.code = code;}@Overridepublic String getMessage() {return TextUtils.isEmpty(message) ? "" : message;}public int getCode() {return code;}private int code;private String message;}

? 3.2.3?HttpInterceptor請求攔截器


/*** 自定義* 請求攔截器** @author shizhiyin*/public class HttpInterceptor implements Interceptor {private static final Charset UTF8 = Charset.forName("UTF-8");private static String REQUEST_TAG = "請求";/*** 通過攔截器* 添加請求頭* 及* 打印請求結果*/@Overridepublic Response intercept(Chain chain) throws IOException {if (!NetworkUtils.isConnected()) {throw new HttpException("網絡連接異常,請檢查網絡后重試");}Request request = chain.request();request = getHeaderRequest(request);//打印請求logRequest(request);Response response = chain.proceed(request);//
//        if (!response.headers("Set-Cookie").isEmpty()) {
//            HashSet<String> cookies = new HashSet<>();
//            for (String header : response.headers("Set-Cookie")) {
//                cookies.add(header);
//            }
//            Hawk.put(Constants.HawkCode.COOKIE, cookies);
//        }////打印響應logResponse(response);return response;}/*** 添加header*/public Request getHeaderRequest(Request request) {//        LoginRequestBean loginData =null;LoginRequestBean loginData = Hawk.get(Constants.HawkCode.LOGIN_TOKEN_INFO);Request headRequest;if (loginData != null) {
//            Logger.d("===緩存獲取token=="+loginData.getToken());headRequest = request.newBuilder().addHeader("Content-Type", "application/json").addHeader("terminal", "doctor").addHeader("Authorization", loginData.getToken()).build();} else {headRequest = request.newBuilder().addHeader("Content-Type", "application/json").addHeader("terminal", "doctor").build();}return headRequest;}/*** 打印請求信息** @param request*/private void logRequest(Request request) {Log.d(REQUEST_TAG + "method", request.method());Log.d(REQUEST_TAG + "url", request.url().toString());Log.d(REQUEST_TAG + "header", request.headers().toString());if (request.method().equals("GET")) {return;}try {RequestBody requestBody = request.body();String parameter = null;Buffer buffer = new Buffer();requestBody.writeTo(buffer);parameter = buffer.readString(UTF8);buffer.flush();buffer.close();Log.d(REQUEST_TAG + "參數", parameter);} catch (IOException e) {e.printStackTrace();}}/*** 打印返回結果** @param response*/private void logResponse(Response response) {try {ResponseBody responseBody = response.body();String rBody = null;BufferedSource source = responseBody.source();source.request(Long.MAX_VALUE);Buffer buffer = source.buffer();Charset charset = UTF8;MediaType contentType = responseBody.contentType();if (contentType != null) {try {charset = contentType.charset(UTF8);} catch (UnsupportedCharsetException e) {e.printStackTrace();}}rBody = buffer.clone().readString(charset);
//            Logger.d("===business==響應體==="+rBody);Log.d(REQUEST_TAG + "返回值", rBody);} catch (IOException e) {e.printStackTrace();}}
}

3.2.4.ResponseConverterFactory處理服務器返回數據將數據轉換成對象


/*** 處理服務器返回數據* 將數據轉換成對象** @author shizhiyin*/
public class ResponseConverterFactory extends Converter.Factory {private final Gson mGson;public ResponseConverterFactory(Gson gson) {this.mGson = gson;}public static ResponseConverterFactory create() {return create(new Gson());}public static ResponseConverterFactory create(Gson gson) {if (gson == null) throw new NullPointerException("gson == null");return new ResponseConverterFactory(gson);}@Overridepublic Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {return new BaseResponseBodyConverter(type);}@Overridepublic Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {return GsonConverterFactory.create().requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit);}private class BaseResponseBodyConverter<T> implements Converter<ResponseBody, T> {private Type mType;private BaseResponseBodyConverter(Type mType) {this.mType = mType;}@Overridepublic T convert(ResponseBody response) {Object object;try {String strResponse = response.string();if (TextUtils.isEmpty(strResponse)) {throw new HttpException("返回值是空的—-—");}if (HttpFactory.httpResponseInterface == null) {throw new HttpException("請實現接口HttpResponseInterface—-—");} else {
//                    String strData = HttpFactory.httpResponseInterface.getResponseData(mGson, strResponse);
//                    Logger.d("==login返回值是=="+strData.toString());// strResponse 保留接口返回的全部數據// strData 只保留接口返回的data數據object = mGson.fromJson(strResponse, mType);}} catch (Exception e) {throw new HttpException(e.getMessage());} finally {response.close();}return (T) object;}}
}

?3.2.5?UploadUtils 文件上傳


/*** Created by shizhiyin.* Time:2023年10月16日.* Retrofit文件上傳*/public class UploadUtils {private static final String FILE_NOT_NULL = "文件不能為空";private static final String FILE_PATH_NOT_NULL = "文件路徑不能為空";public static MultipartBody.Part getMultipartBody(String path) {if (TextUtils.isEmpty(path)) throw new NullPointerException(FILE_PATH_NOT_NULL);File file = new File(path);if (file.exists()) {RequestBody requestFile =RequestBody.create(MediaType.parse("application/octet-stream"), file);MultipartBody.Part body =MultipartBody.Part.createFormData("imgFile", file.getName(), requestFile);return body;} else {
//      throw new NullPointerException(FILE_NOT_NULL);return null;}}public static MultipartBody.Part getMultipartBody(File file) {if (file.exists()) {RequestBody requestFile =RequestBody.create(MediaType.parse("application/octet-stream"), file);MultipartBody.Part body =MultipartBody.Part.createFormData("file", file.getName(), requestFile);return body;} else {throw new NullPointerException(FILE_NOT_NULL);}}public static List<MultipartBody.Part> getMultipartBodysForFile(List<File> files) {if (files.isEmpty()) throw new NullPointerException(FILE_NOT_NULL);MultipartBody.Builder builder = new MultipartBody.Builder();for (File file : files) {if (file.exists()) {RequestBody requestFile =RequestBody.create(MediaType.parse("application/octet-stream"), file);builder.addFormDataPart("file", file.getName(), requestFile);} else {throw new NullPointerException(FILE_NOT_NULL);}}return builder.build().parts();}public static List<MultipartBody.Part> getMultipartBodysForPath(List<String> paths) {if (paths.isEmpty()) throw new NullPointerException(FILE_PATH_NOT_NULL);MultipartBody.Builder builder = new MultipartBody.Builder();for (String path : paths) {File file = new File(path);if (file.exists()) {RequestBody requestFile =RequestBody.create(MediaType.parse("application/octet-stream"), file);builder.addFormDataPart("file", file.getName(), requestFile);} else {throw new NullPointerException(FILE_NOT_NULL);}}return builder.build().parts();}
}

3.3 request

3.3.1.ApiAddress網絡請求接口地址


public interface ApiAddress {/*** 新增原生登錄接口* LogingResponseBean*/@POST("auth/login")Observable<LogingResponseBean> LoginPost(@Body JSONObject parmas);
}

3.3.2.HttpFactory網絡請求


/*** @author shizhiyin* 網絡請求*/
public class HttpFactory {public static String HTTP_HOST_URL = "";public static HttpResponseInterface httpResponseInterface = null;private HttpFactory() {}/*** 設置HttpClient*/private static OkHttpClient HTTP_CLIENT =new Builder()//添加自定義攔截器.addInterceptor(new HttpInterceptor()).addInterceptor(new AddCookiesInterceptor())//設置超時時間.connectTimeout(60, TimeUnit.SECONDS).readTimeout(60, TimeUnit.SECONDS).build();private static Retrofit retrofit = null;public static <T> T getChangeUrlInstance(String url, Class<T> service) {return new Retrofit.Builder().baseUrl(url).addConverterFactory(ResponseConverterFactory.create()).addCallAdapterFactory(RxJava2CallAdapterFactory.create()).client(HTTP_CLIENT).build().create(service);}public static <T> T getInstance(Class<T> service) {if (retrofit == null) {retrofit = new Retrofit.Builder().baseUrl(HTTP_HOST_URL).addConverterFactory(ResponseConverterFactory.create()).addCallAdapterFactory(RxJava2CallAdapterFactory.create()).client(HTTP_CLIENT).build();}return retrofit.create(service);}@SuppressWarnings("unchecked")public static <T> ObservableTransformer<T, T> schedulers() {return new ObservableTransformer<T, T>() {@Overridepublic ObservableSource<T> apply(Observable<T> upstream) {return upstream.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());}};}
}

3.3.3HttpRequest


/*** @author shizhiyin*/
public class HttpRequest {private static ApiAddress Instance;public static ApiAddress getInstance() {if (Instance == null) {synchronized (HttpRequest.class) {if (Instance == null) {Instance = HttpFactory.getInstance(ApiAddress.class);}}}return Instance;}public static ApiAddress getInstance(String url) {return HttpFactory.getChangeUrlInstance(url, ApiAddress.class);}}

3.3.4ServerAddress


/*** 服務器地址** @author shizhiyin*/
public class ServerAddress {public static final String API_DEFAULT_HOST = "https://........com/";
}

四、使用

4.1.在應用的applacation中初始化

/*** 請求配置*/public static void setHttpConfig() {HttpFactory.HTTP_HOST_URL = ServerAddress.getApiDefaultHost();HttpFactory.httpResponseInterface = (gson, response) -> {if (firstOpen) {firstOpen = false;return response;}HttpBaseResponse httpResponse = gson.fromJson(response, HttpBaseResponse.class);if (httpResponse.errorCode != 0) {throw new HttpException(httpResponse.errorCode, httpResponse.errorMsg);}return gson.toJson(httpResponse.data);};}

4.2.請求示例

 private void login(String name, String pwd) {LoginRequestBean loginRequestBean = new LoginRequestBean(name, pwd);HttpRequest.getInstance(ServerAddress.BASE_URL).LoginPost((JSONObject) JSON.toJSON(loginRequestBean)).compose(HttpFactory.schedulers()).subscribe(new HttpDisposable<LogingResponseBean>() {@Overridepublic void success(LogingResponseBean bean) {}@Overridepublic void onError(Throwable e) {super.onError(e);Logger.d("====login=登錄onError==" + e.toString());}});}

最后要感謝玩Android開源平臺提供的參考。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/208310.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/208310.shtml
英文地址,請注明出處:http://en.pswp.cn/news/208310.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

JVM虛擬機:執行Java程序并指定JVM參數

本文重點 在前面我們設置參數值的時候&#xff0c;需要在eclipse中的VM中進行參數設置&#xff0c;查詢的時候需要先jps&#xff0c;然后jinfo。這里嘗試動態的設置和查詢&#xff0c;也就是說在運行程序的時候就對其進行設置&#xff0c;并且進行查詢。 過程 為了確定參數修…

微信個人號機器人開發

簡要描述&#xff1a; 取消消息接收 請求URL&#xff1a; http://域名地址/cancelHttpCallbackUrl 請求方式&#xff1a; POST 請求頭Headers&#xff1a; Authorization&#xff1a;login接口返回Content-Type&#xff1a;application/json 無參數 返回數據&#xff…

MeteoInfo-Java解析與繪圖教程

MeteoInfo-Java解析與繪圖教程(四) 上文我們說到,將地圖疊加在色斑圖上,但大部分都是衛星繪圖,現在開始講解micaps數據繪圖,同樣也是更多自定義 配置 首先我們解析micaps數據,將之前學到的東西拿過來繪圖 MeteoDataInfo meteoDataInfo new MeteoDataInfo(); meteoDataInfo.o…

使用Binding的RelativeSource

一個Binding有明確的數據來源 可以通過Source或ElementName賦值的方法讓Binding與之關聯 但是有的時候我們不能確定作為Source的對象叫什么名字&#xff0c;但知道它與作為Binding目標的對象在UI上有相對關系&#xff0c;比如&#xff1a;空間自己關聯自己的某個數據、關聯自己…

Flutter代碼補全

有的時候屬性不經常使用&#xff0c;就想不起來該用啥&#xff0c;只有點點印象&#xff1b;只能用代碼補全功能&#xff0c;但我用了AS的默認操作發下并不好使&#xff0c;估計是快捷鍵沖突了。剛開始是不是下面的效果&#xff1a;這肯定不是我們想要的。 不怕&#xff0c;接下…

【S32DS報錯】-2-提示Error while launching command:arm-none-eabi-gdb –version錯誤

目錄 1 Error錯誤提示 2 Error錯誤原因 3 如何消除Error錯誤 結尾 【S32K3_MCAL從入門到精通】合集&#xff1a; S32K3_MCAL從入門到精通https://blog.csdn.net/qfmzhu/category_12519033.html 1 Error錯誤提示 使用S32DSJ-LinK下載程序&#xff0c;在Dedug Configurati…

計算機基礎知識67--BBS

遷移表格 # 以后你寫的每個python項目&#xff0c;都必須有一個txt文件叫 requirements.txt,里面放了當前項目所有的依賴&#xff0c;別人拿到項目---》需要執行 pip install -r requirements.txt # 裝好該項目所有依賴 django3.2.20 # 模塊 pillow mysqlclient # 主體項目功…

中東電商指南分享!盤點中東四大跨境電商平臺

提到跨境電商新藍海&#xff0c;就不得不想起土豪聚集地 ——中東&#xff0c;中東地區擁有龐大的人口、高人均GDP、強大的消費能力以及廣泛普及的互聯網&#xff0c;但外出購物卻相對不便&#xff0c;正是這一特點為中東跨境電商市場創造了巨大的優勢。隨著中東地區電商的崛起…

mycat實現分表操作、isinstance的使用、sqlalchemy的使用、mysql數據庫連接池

1 mycat實現分表操作 2 isinstance的使用 3 sqlalchemy的使用 4 mysql數據庫連接池 1 mycat實現分表操作 在 MySQL 數據庫中&#xff0c;Mycat 通常用于實現分片&#xff08;Sharding&#xff09;操作。分片是一種將大型數據庫水平拆分成多個較小數據庫的策略&#xff0c;以提…

Gan論文閱讀筆記

GAN論文閱讀筆記 2014年老論文了&#xff0c;主要記錄一些重要的東西。論文鏈接如下&#xff1a; Generative Adversarial Nets (neurips.cc) 文章目錄 GAN論文閱讀筆記出發點創新點設計訓練代碼網絡結構代碼測試代碼 出發點 Deep generative models have had less of an impac…

軟件壓力測試的重要性與用途

在當今數字化的時代&#xff0c;軟件已經成為幾乎所有行業不可或缺的一部分。隨著軟件應用規模的增加和用戶數量的上升&#xff0c;軟件的性能變得尤為關鍵。為了確保軟件在面對高并發和大負載時仍然能夠保持穩定性和可靠性&#xff0c;軟件壓力測試變得至關重要。下面是軟件壓…

提醒事項日歷同步怎么設置?可實時同步日歷的提醒事項工具

隨著生活節奏的加快&#xff0c;我們每天都需要處理許多瑣碎的事務。為了不忘記重要的事情&#xff0c;很多人選擇使用提醒事項工具來幫助自己。然而&#xff0c;市場上的提醒事項工具五花八門&#xff0c;有些并不具備日歷月視圖功能&#xff0c;也無法與手機日歷同步&#xf…

JavaScript 復雜的<三元運算符和比較操作>的組合--案例(一)

在逆向的時候,碰上有些復雜的js代碼,邏輯弄得人有點混; 因此本帖用來記錄一些棘手的代碼,方便自己記憶,也讓大家拓展認識~ ----前言 內容: function(e, t, n) {try {1 (e "{" e[0] ? JSON.parse(e) : JSON.parse(webInstace.shell(e))).Status || 200 e.Code…

Linux學習筆記7-IIC的應用和AP3216C

接下來進入其他兩種串行通信方式&#xff1a;SPI和I2C的學習&#xff0c;因為以后的項目中會用到這些通信方式&#xff0c;而且正點原子的開發板里面也有用I2C和SPI通信的傳感器來做實例&#xff0c;分別是一個距離傳感器和六軸陀螺儀&#xff0c;這樣就可以很好的通過實例來學…

GRE與順豐圓通快遞盒子

1. DNS污染 隨想&#xff1a; 在輸入一串網址后&#xff0c;會發生如下變化如果你在系統中配置了 Hosts 文件&#xff0c;那么電腦會先查詢 Hosts 文件如果 Hosts 里面沒有這個別名&#xff0c;就通過域名服務器查詢域名服務器回應了&#xff0c;那么你的電腦就可以根據域名服…

第六屆“強網”擬態防御國際精英挑戰賽——入圍戰隊篇

第六屆“強網”擬態防御國際精英挑戰賽即將于2023年12月6日在南京盛大開賽&#xff01;本屆挑戰賽再次為全球頂尖戰隊提供實戰機會&#xff0c;向多類擬態防御設備系統發起挑戰&#xff0c;在眾測實戰中持續檢驗中國制造內生安全數字產品所具有的中國力量。 本屆挑戰賽參賽戰隊…

【LeetCode:1466. 重新規劃路線 | DFS + 圖 + 樹】

&#x1f680; 算法題 &#x1f680; &#x1f332; 算法刷題專欄 | 面試必備算法 | 面試高頻算法 &#x1f340; &#x1f332; 越難的東西,越要努力堅持&#xff0c;因為它具有很高的價值&#xff0c;算法就是這樣? &#x1f332; 作者簡介&#xff1a;碩風和煒&#xff0c;…

Vue 子路由頁面發消息給主路由頁面 ,實現主頁面顯示子頁面的信息

需求 子頁面進入后&#xff0c;能在主頁面顯示子頁的相關信息&#xff0c;比如說主頁面的菜單激活的是哪個子頁面的菜單項 如上圖&#xff0c;當刷新瀏覽器頁面時&#xff0c;讓菜單的激活項仍保持在【最近瀏覽】。 實現方式&#xff1a; 在子頁面的create事件中增加&#xff…

Java File類詳解(下)練習一

練習 第一題 需求&#xff1a;在當前模塊下的aaa文件夾中創建一個a.txt文件 import java.io.File; import java.io.IOException;public class FileExer01 {public static void main(String[] args) throws IOException {File f1 new File("AllInOne\\aaa");f1.mk…

docker-compose腳本編寫關鍵詞詳解

docker-compose腳本編寫高頻關鍵詞&#xff08;一&#xff09; 此處關鍵詞應該必須能靈活運用 關鍵詞 解釋 例子 version 定義使用的docker-compose文件版本。較新的版本支持更豐富的功能和選項。 version: 3.8 services 定義應用程序的各個服務及其配置。每個服務通常…