好几年前封装的框架一直没上传,趁现在升级写下。
简介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开源平台提供的参考。