一、需要添加的依赖包
// Retrofit+OKHttp
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0'
implementation 'com.squareup.okhttp3:okhttp:3.14.2'
implementation 'com.squareup.okhttp3:logging-interceptor:3.11.0'
//RxJava2
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation 'io.reactivex.rxjava2:rxjava:2.2.8'
//AutoDispose
implementation 'com.uber.autodispose:autodispose-android-archcomponents:1.3.0'
二、基础使用
website
public interface ApiService {
@GET("article/list/{page}/json")
Call> getArticle(@Path("page") int pageNo);
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://www.wanandroid.com")
.build();
ApiService service = retrofit.create(ApiService.class);
service.getArticle(1)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(BaseResponse articleListBaseResponse) {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
三、Retrofit封装
public class ApiClient {
private static final String BASE_URL = "https://www.wanandroid.com";
private static final int TIMEOUT_CONNECTION = 30;
private static final int TIMEOUT_READ = 60;
private static final int TIMEOUT_WRITE = 60 * 3;
private static ApiClient mInstance;
private Retrofit mRetrofit;
private ApiClient() {
initialize();
}
public static ApiClient getInstance() {
if (mInstance == null) {
synchronized (ApiClient.class) {
if (mInstance == null) {
mInstance = new ApiClient();
}
}
}
return mInstance;
}
public void initialize() {
mRetrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(initClient())
.build();
}
private OkHttpClient initClient() {
Interceptor interceptor = chain -> {
Request.Builder requestBuilder = chain.request().newBuilder();
requestBuilder.addHeader("test", "test");
return chain.proceed(requestBuilder.build());
};
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(TIMEOUT_CONNECTION, TimeUnit.SECONDS) //连接超时
.readTimeout(TIMEOUT_READ, TimeUnit.SECONDS) //读取超时
.writeTimeout(TIMEOUT_WRITE, TimeUnit.SECONDS) //写入超时
.addInterceptor(interceptor)
.retryOnConnectionFailure(true); //断线重连
//Log信息拦截器
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(BuildConfig.DEBUG ? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.NONE);
builder.addInterceptor(loggingInterceptor);
return builder.build();
}
public T create(Class clazz) {
return mRetrofit.create(clazz);
}
public UserService getApiService() {
return mRetrofit.create(UserService.class);
}
}
四、线程切换
public final class RxScheduler {
public static ObservableTransformer io2Main() {
return upstream -> upstream
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
}
五、统一处理结果
public class BaseResponse {
private int errorCode;
private String errorMsg;
private T data;
public int getErrorCode() {
return errorCode;
}
public void setErrorCode(int errorCode) {
this.errorCode = errorCode;
}
public String getErrorMsg() {
return errorMsg;
}
public void setErrorMsg(String errorMsg) {
this.errorMsg = errorMsg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
Service中使用
@GET("data")
Observable getData();
@GET("datas/{page}")
Observable>> getDatas(@Path("page") int pageNo);
六、统一错误处理和结果处理
网络错误可以大致分为两种,一种是网络请求中的错误、一种是服务器返回的业务错误。下面简称网络错误和业务错误,我们需要把网络错误转换成可对用户提示的错误。
/**
* 业务异常类型
* 把网络错误转换成业务错误
*/
public enum NetworkErrorType {
BAD_GATEWAY(500, R.string.service_error),
NOT_FIND(404, R.string.service_error),
NETWORK_NOT_CONNECT(300, R.string.offline_error),
UNEXPECTED_ERROR(301, R.string.parse_error),
UNKNOWN_ERROR(304, R.string.unknown_error),
TIMEOUT_ERROR(504, R.string.timeout_error);
private final int code;
private final int messageId;
public int getCode() {
return code;
}
public int getMessageId() {
return messageId;
}
NetworkErrorType(int code, @StringRes int messageId) {
this.code = code;
this.messageId = messageId;
}
public NetworkErrorModel getErrorModel() {
return new NetworkErrorModel(code, App.getInstance().getString(messageId));
}
}
/**
* 网络错误对象
*/
public class NetworkErrorModel {
private int code;
private String message;
public NetworkErrorModel(int code, String string) {
this.code = code;
this.message = string;
}
public void setCode(int code) {
this.code = code;
}
public void setMessage(String message) {
this.message = message;
}
public int getCode() {
return code;
}
public String getMessage() {
return message;
}
}
final class UnifiedErrorUtil {
static NetworkErrorType handlerError(Throwable e) {
NetworkErrorType networkErrorType;
if (e instanceof UnknownHostException) {
networkErrorType = NetworkErrorType.NETWORK_NOT_CONNECT;
} else if (e instanceof SocketTimeoutException) {
networkErrorType = NetworkErrorType.TIMEOUT_ERROR;
} else if (e instanceof ConnectException) {
networkErrorType = NetworkErrorType.NETWORK_NOT_CONNECT;
} else if (e instanceof SSLHandshakeException) {
networkErrorType = NetworkErrorType.NETWORK_NOT_CONNECT;
} else {
networkErrorType = NetworkErrorType.UNKNOWN_ERROR;
}
return networkErrorType;
}
}
public abstract class ResponseObserver implements Observer {
public static final int SUCCESS_CODE = 0;
public abstract void success(T t);
public abstract void failure(int statusCode, NetworkErrorModel networkErrorModel);
@Override
public void onSubscribe(Disposable d) {
showLoading();
}
@Override
public void onNext(T t) {
success(t);
}
@Override
public void onError(Throwable e) {
cancelLoading();
NetworkErrorType networkErrorType = UnifiedErrorUtil.handlerError(e);
failure(networkErrorType.getCode(), networkErrorType.getErrorModel());
}
@Override
public void onComplete() {
cancelLoading();
}
private void showLoading() {
// Do not implement
}
private void cancelLoading() {
// Do not implement
}
}
七、自动取消订阅
使用RxJava发布一个订阅后,当Activity被finish,此时订阅逻辑还未完成,如果没有及时取消订阅,就会导致Activity无法被回收,从而引发内存泄漏。
我们使用AutoDispose 来解决Rxjava 泄露问题。
前提:
- 需要先将项目迁移至AndroidX
- 依赖Android Architecture Components中的Lifecycle 框架,需要Support Library 26.1.0 及其以后的版本
public final class AutoDisposeHelp {
public static AutoDisposeConverter bindAutoDispose(LifecycleOwner owner) {
return AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(owner, Lifecycle.Event.ON_DESTROY));
}
}
八、其他
最后使用效果,只是一个简单的封装,需要其他更多的需求大家自己扩展。
ApiClient.getInstance().getApiService().fetchRequestVinylList(0)
.compose(RxScheduler.io2Main())
.as(AutoDisposeHelp.bindAutoDispose(this))
.subscribe(new ResponseObserver() {
@Override
public void success(BaseListMessage baseListMessage) {
if (baseListMessage.getErrorCode() == SUCCESS_CODE) {
//服务器成功
} else {
//服务器业务错误
}
}
@Override
public void failure(int statusCode, NetworkErrorModel networkErrorModel) {
Toast.makeText(MainActivity.this, networkErrorModel.getMessage(), Toast.LENGTH_SHORT).show();
}
});