最近在重构公司的网络层,准备使用最近比较火的组合,采用Retrofit搭配Rx,下面是基础部分一些实践和心得。
1. 初始化
1 2 3 4 5 6 7
| Retrofit retrofit = new Retrofit.Builder() .baseUrl(NetWorkManager.BASE_URL) .addConverterFactory(LiveStarConverterFactory.create(GsonUtils.getGson())) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .callFactory(createOkHttpClient()) .build(); sLiveStarApi = retrofit.create(LiveStarApi.class);
|
配置基本的url、数据解析和数据请求方式。
2.添加通用参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| static OkHttpClient createOkHttpClient() { return OkHttpClientProvider.getDefaultOkHttpClient() .newBuilder() .addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request();
request = interceptRequest(request);
return chain.proceed(request); } }) .build(); }
static Request interceptRequest(Request request) { RequestBody requestBody = request.body(); if (requestBody == null) {
}else if (requestBody instanceof FormBody) { FormBody formBody = (FormBody) requestBody; Map<String, String> params = new HashMap<>(); for (int i = 0; i < formBody.size(); i ++) { String name = formBody.name(i); String value = formBody.value(i); params.put(name, value); }
appendRequestBody(params);
formBody = generateRequestBody(params);
request = request.newBuilder().post(formBody).build(); }else if (requestBody instanceof MultipartBody) { MultipartBody multipartBody = (MultipartBody) requestBody; MultipartBody.Builder builder = new MultipartBody.Builder(); builder.setType(multipartBody.type()); long time = System.currentTimeMillis() / 1000; String flag = MD5Util.getStringMD5(Contant.USER_IMG_UPLOAD_KEY + time); builder.addFormDataPart("time", String.valueOf(time)); builder.addFormDataPart("flag", flag);
for (MultipartBody.Part part : multipartBody.parts()) { builder.addPart(part); }
request = request.newBuilder().post(builder.build()).build(); }
return request; }
|
这里就是通过okhttp的拦截器添加通用参数。 因为涉及到具体业务, 所以不详细贴代码。
3.创建基础Response类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| public class LiveStarResponse {
private int code; private String message; private boolean state;
public int getCode() { return code; }
public void setCode(int code) { this.code = code; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
public boolean isState() { return state; }
public void setState(boolean state) { this.state = state; }
public boolean isSuccessful() { return code == ResponseCode.SUCCESS && state; } }
|
4. 返回错误处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class ErrorCheckerTransformer<T extends LiveStarResponse> implements Observable.Transformer<T, T> {
@Override public Observable<T> call(Observable<T> observable) { return observable.map(new Func1<T, T>() { @Override public T call(T t) { if (!t.isSuccessful()) { throw new RuntimeException(new ErrorResponseException(t)); } else { return t; } } }); }
public static <T extends LiveStarResponse> ErrorCheckerTransformer<T> create() { return new ErrorCheckerTransformer<>(); } }
|
5. 配置线程
1 2 3 4 5 6 7 8 9 10 11 12
| public class SchedulerTransformer<T> implements Observable.Transformer<T, T> { @Override public Observable<T> call(Observable<T> observable) { return observable .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); }
public static <T> SchedulerTransformer<T> create() { return new SchedulerTransformer<>(); } }
|
6. 创建返回错误统一处理方案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| public abstract class DefaultResponseSubscriber<T> extends Subscriber<T> {
private BaseView mBaseView;
public DefaultResponseSubscriber(BaseView baseView) { mBaseView = baseView; }
public void onError(Throwable e) { String hint; if (e instanceof IOException) { hint = App.getContext().getString(R.string.no_netwrok_hint); }else if (e instanceof HttpException){ HttpException httpException = (HttpException) e; hint = "Http Exception" + httpException.code() + " " + httpException.message(); }else if (e instanceof RuntimeException && e.getCause() instanceof ErrorResponseException) { ErrorResponseException errorResponseException = (ErrorResponseException) e.getCause(); if (errorResponseException.getResponse().getCode() == 309) { mBaseView.onAuthError(); return; }else { hint = errorResponseException.getResponse().getMessage(); } }else { hint = e.getMessage(); }
onFail(e, hint); }
protected abstract void onFail(Throwable e, String hint);
}
|
7. 开始请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| mCashOutManager.cashOutSwitch() .compose(ErrorCheckerTransformer.<CheckCashOutResponse>create()) .compose(SchedulerTransformer.<CheckCashOutResponse>create()) .doOnSubscribe(new Action0() { @Override public void call() { mCashOutView.showLoading(true); } }).doOnTerminate(new Action0() { @Override public void call() { mCashOutView.showLoading(false); } }).subscribe(new DefaultResponseSubscriber<CheckCashOutResponse>(mCashOutView) { @Override protected void onFail(Throwable e, String hint) { mCashOutView.onError(hint); }
@Override public void onCompleted() {
}
@Override public void onNext(CheckCashOutResponse response) { if (response.isSuccessful() && response.getData() != null && !TextUtils.isEmpty(response.getData().getUrl())) { mCashOutView.onCashOutCheckSuccess(response); }else { mCashOutView.onCashOutCheckError(App.getContext().getString(R.string.star_money_tip)); } } });
|
8. 遇到的一些坑
在涉及到MultipartBody的时候GosnConverterFactory默认是MediaType.parse(“application/json; charset=UTF-8”),其实并不是json的格式,会导致请求失败问题。所以我采用自定义RequestBodyConverter对改变基本类型MediaType
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| final class RequestBodyConverter<T> implements Converter<T, RequestBody> { private static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=UTF-8"); private static final Charset UTF_8 = Charset.forName("UTF-8");
private final Gson gson; private final TypeAdapter<T> adapter;
RequestBodyConverter(Gson gson, TypeAdapter<T> adapter) { this.gson = gson; this.adapter = adapter; }
@Override public RequestBody convert(T value) throws IOException { if (value instanceof String || value instanceof Long || value instanceof Integer) { return RequestBody.create(null, String.valueOf(value)); }else { Buffer buffer = new Buffer(); Writer writer = new OutputStreamWriter(buffer.outputStream(), UTF_8); JsonWriter jsonWriter = gson.newJsonWriter(writer); adapter.write(jsonWriter, value); jsonWriter.close(); return RequestBody.create(MEDIA_TYPE_JSON, buffer.readByteString()); } } }
|