Retrofit本质上是网络请求的封装库,并没有参与真正的网络请求操作,他为我们提供丰富的注解,用更优雅的方式包装网络请求需要的各个元素;
OkHttp完成真正的网络请求操作,接收Retrofit获取的请求地址、请求头、参数等信息发起网络请求,获取网络数据;
RxJava处理异步操作,他提供了丰富强大的操作符,使用RxJava来完成网络请求过程中繁琐的线程调度;
AutoDispose,使用AutoDispose让网络请求订阅事件与Activity/Fragment生命周期关联,在页面销毁时,取消网络请求订阅事件,避免因为网络请求结果未返回用户关闭页面引起的内存泄露问题。
1、申请网络权限
<uses-permission android:name="android.permission.INTERNET" />
2、Android 9.0以后对不安全链接做了限制,推荐使用https请求,如果使用http需要配置如下:
在res资源文件目录下新建xml文件夹,新建network_security_config.xml文件
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>
在应用application节点下配置
android:networkSecurityConfig="@xml/network_security_config"
3、引入所需依赖
// 网络组件
api 'com.squareup.retrofit2:retrofit:2.5.0'
api 'com.squareup.retrofit2:converter-gson:2.5.0'
api 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
api 'com.squareup.retrofit2:converter-scalars:2.5.0'
api 'com.squareup.okhttp3:logging-interceptor:4.7.2'
// 异步组件
api 'io.reactivex.rxjava2:rxandroid:2.1.1'
api 'io.reactivex.rxjava2:rxjava:2.2.19'
// rxjava扩展
api 'com.uber.autodispose:autodispose-android-archcomponents:1.3.0'
// json解析
api 'com.google.code.gson:gson:2.8.9'
4、核心类RetrofitHelper,使用单例模式
public class RetrofitHelper {
//baseUrl
public static String BASE_URL;
private static volatile RetrofitHelper instance;
private final Retrofit.Builder retrofitBuilder;
/**
* 使用默认BASE_URL
*
* @return
*/
public Retrofit getRetrofit() {
return getRetrofit(null);
}
/**
* 方法重载
*
* @param baseUrl baseUrl不为空,替换默认BASE_URL
* @return
*/
public Retrofit getRetrofit(String baseUrl) {
Retrofit retrofit;
if (TextUtils.isEmpty(baseUrl)) {
retrofit = retrofitBuilder.baseUrl(BASE_URL).build();
} else {
retrofit = retrofitBuilder.baseUrl(baseUrl).build();
}
return retrofit;
}
private RetrofitHelper() {
//默认BASE_URL赋值
BASE_URL = "http://www.baidu.com/";
//构建OkHttpClient对象
OkHttpClient.Builder builder = new OkHttpClient.Builder();
//日志拦截器
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
builder.addInterceptor(loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY))
.addInterceptor(getRequestInterceptor())
.addInterceptor(getHeaderInterceptor())
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(45, TimeUnit.SECONDS)
.writeTimeout(45, TimeUnit.SECONDS)
.retryOnConnectionFailure(true);
OkHttpClient okHttpClient = builder.build();
//创建retrofit构建者对象
retrofitBuilder = new Retrofit.Builder();
retrofitBuilder.client(okHttpClient)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create());
}
public static RetrofitHelper getInstance() {
if (instance == null) {
synchronized (RetrofitHelper.class) {
if (instance == null) {
instance = new RetrofitHelper();
}
}
}
return instance;
}
/**
* 添加公用的头部内容
*/
@NonNull
private Interceptor getHeaderInterceptor() {
return chain -> {
Request originalRequest = chain.request();
Request.Builder builder = originalRequest.newBuilder();
builder.method(originalRequest.method(), originalRequest.body());
Request request = builder.build();
return chain.proceed(request);
};
}
/**
* 添加公用的 query 参数
*/
@NonNull
private Interceptor getRequestInterceptor() {
return chain -> {
Request originalRequest = chain.request();
// 添加新的参数
HttpUrl.Builder authorizedUrlBuilder = originalRequest.url()
.newBuilder()
.scheme(originalRequest.url().scheme())
.host(originalRequest.url().host())
// .addQueryParameter("clientType", "mobile")
;
// 新的请求
Request newRequest = originalRequest.newBuilder()
.method(originalRequest.method(), originalRequest.body())
.url(authorizedUrlBuilder.build())
.build();
return chain.proceed(newRequest);
};
}
}
5、定义响应模板类,与后台接口约定
/**
* 返回模板类,根据实际情况调整
*/
public class ResponseModel<T> implements Serializable {
/**
* 请求成功code值
*/
public static final int SUCCESS = 0;
private int code;
private String msg;
private T data;
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
@Override
public String toString() {
return "ResponseModel{" +
"code=" + code +
", msg='" + msg + '\'' +
", data=" + data +
'}';
}
}
6、定义网络请求回调接口
public interface CallBackLis<T> {
void onSuccess(String method, T content);
void onFailure(String method, String error);
}
7、网络请求失败,根据异常类型给出友好提示
public class HttpStatusCode {
public static String code2info(int statusCode) {
String info;
switch (statusCode) {
case 200:
info = "请求成功";
break;
case 400:
info = "错误请求";
break;
case 401:
info = "未授权或授权过期";
break;
case 403:
info = "服务器拒绝请求";
break;
case 404:
info = "请求方法不存在";
break;
case 414:
info = "请求地址过长";
break;
case 415:
info = "不支持的媒体类型";
break;
case 500:
info = "服务器内部错误";
break;
case 502:
info = "错误网关";
break;
case 503:
info = "服务不可用";
break;
case 504:
info = "网关超时";
break;
default:
info = "状态码:" + statusCode;
}
return info;
}
public static String handleException(Throwable e) {
if (e instanceof HttpException) {
HttpException httpException = (HttpException) e;
int statusCode = httpException.code();
return code2info(statusCode);
} else if (e instanceof JsonParseException
|| e instanceof JSONException
|| e instanceof ParseException) {
return "解析错误";
} else if (e instanceof ConnectException) {
return "连接超时";
} else if (e instanceof SocketTimeoutException) {
return "响应超时";
} else {
return "未知错误";
}
}
}
8、网络请求回调统一处理类,只保留对我们有用的数据
public class HttpCall {
/**
* 网络请求结果过滤
*
* @param owner
* @param observable
* @param callBackLis
* @param flag
* @param <T>
*/
public static <T> void doCall(LifecycleOwner owner, Observable<ResponseModel<T>> observable, final CallBackLis<T> callBackLis, final String flag) {
if (observable == null || callBackLis == null) {
throw new IllegalArgumentException("observable或callBackLis为空");
}
//观察者_网络请求状态
SimpleObserver<ResponseModel<T>> observer = new SimpleObserver<ResponseModel<T>>() {
@Override
public void onNext(ResponseModel<T> responseModel) {
try {
if (responseModel != null) {
if (responseModel.getCode() == ResponseModel.SUCCESS) {
callBackLis.onSuccess(flag, responseModel.getData());
} else {
callBackLis.onFailure(flag, responseModel.getMsg());
}
} else {
callBackLis.onFailure(flag, "请求数据异常!");
}
} catch (Exception e) {
e.printStackTrace();
callBackLis.onFailure(flag, "解析错误!");
}
}
@Override
public void onError(Throwable e) {
callBackLis.onFailure(flag, HttpStatusCode.handleException(e));
}
};
if (owner == null) {
//被观察者订阅观察者,根据生命周期取消订阅,子线程订阅主线程观察
observable.subscribeOn(Schedulers.newThread())
.unsubscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(observer);
} else {
//被观察者订阅观察者,根据生命周期取消订阅,子线程订阅主线程观察
observable.subscribeOn(Schedulers.newThread())
.unsubscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
//AutoDispose通过LifecycleOwner与Activity生命周期关联,页面销毁时取消网络请求订阅
.as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(owner, Lifecycle.Event.ON_DESTROY)))
.subscribe(observer);
}
}
/**
* 该方法不过滤返回数据
*
* @param owner
* @param observable
* @param callBackLis
* @param flag
* @param <T>
*/
public static <T> void doCallWithoutIntercept(LifecycleOwner owner, Observable<T> observable, final CallBackLis<T> callBackLis, final String flag) {
if (observable == null || callBackLis == null) {
throw new IllegalArgumentException("observable或callBackLis为空");
}
//观察者_网络请求状态
SimpleObserver<T> observer = new SimpleObserver<T>() {
@Override
public void onNext(T t) {
try {
if (t != null) {
callBackLis.onSuccess(flag, t);
} else {
callBackLis.onFailure(flag, "请求数据异常!");
}
} catch (Exception e) {
e.printStackTrace();
callBackLis.onFailure(flag, "解析错误!");
}
}
@Override
public void onError(Throwable e) {
callBackLis.onFailure(flag, HttpStatusCode.handleException(e));
}
};
if (owner == null) {
observable.subscribeOn(Schedulers.newThread())
.unsubscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(observer);
} else {
observable.subscribeOn(Schedulers.newThread())
.unsubscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
//AutoDispose通过LifecycleOwner与Activity生命周期关联,页面销毁时取消网络请求订阅
.as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(owner, Lifecycle.Event.ON_DESTROY)))
.subscribe(observer);
}
}
}
通过以上操作,网络请求库就封装完成了,使用方法如下:
1、创建Retrofit接口Api,定义接口方法
//加入RxJava之后,定义返回类型为Observable类型
@POST("拼接参数")
Observable<ResponseModel<具体data类型>> login(@Body RequestBody requestBody);
2、创建HttpRequest类
public static void login(LifecycleOwner owner, CallBackLis<具体data类型> callBackLis) {
RequestBody requestBody = HttpUtils.getRequestBody("{\"loginName\":\"loginName\"}");
Observable<ResponseModel<具体data类型>> observable = RetrofitHelper
.getInstance()
.getRetrofit()
.create(Api.class)
.login(requestBody);
HttpCall.doCall(owner, observable, callBackLis, null);
}
3、在Activity/Fragment中调用方法
HttpRequest.login(activity, new CallBackLis<具体data类型>() {
@Override
public void onSuccess(String method, 具体data类型 content) {
//content为我们需要的数据
}
@Override
public void onFailure(String method, String error) {
toast(error);
}
});