好幾年前封裝的框架一直沒上傳,趁現在升級寫下。
? ? ?簡介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.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開源平臺提供的參考。