Rxjava+ReTrofit+okHttp深入浅出-终极封装
- - CSDN博客推荐文章Rxjava+ReTrofit+okHttp深入浅出-终极封装. 学习Rxjava和retrofit已经很长时间了,功能确实很强大,但是使用起来还是有点复杂,代码的重复性太高,所以决定把基于retrofit和rxjava的处理统一封装起来,实现的功能:. 1.Retrofit+Rxjava+okhttp基本使用方法.
1.Retrofit+Rxjava+okhttp基本使用方法
2.统一处理请求数据格式
3.统一的ProgressDialog和回调Subscriber处理
4.取消http请求
5.预处理http请求
5.返回数据的统一判断
// 完美封装简化版 private void simpleDo() { SubjectPost postEntity = new SubjectPost(new ProgressSubscriber(simpleOnNextListener, this), true); HttpManager manager = HttpManager.getInstance(); manager.doHttpDeal(postEntity); } // 回调一一对应 HttpOnNextListener simpleOnNextListener = new HttpOnNextListener<List<Subject>>() { @Override public void onNext(List<Subject> subjects) { tvMsg.setText("已封装:\n" + subjects.toString()); } };>是不是很简单?你可能说这还简单,好咱们对比一下正常使用retrofit的方法
/** * Retrofit加入rxjava实现http请求 */ private void onButton9Click() { //手动创建一个OkHttpClient并设置超时时间 okhttp3.OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.connectTimeout(5, TimeUnit.SECONDS); Retrofit retrofit = new Retrofit.Builder() .client(builder.build()) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .baseUrl(HttpManager.BASE_URL) .build(); // 加载框 final ProgressDialog pd = new ProgressDialog(this); HttpService apiService = retrofit.create(HttpService.class); Observable<RetrofitEntity> observable = apiService.getAllVedioBy(true); observable.subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) .subscribe( new Subscriber<RetrofitEntity>() { @Override public void onCompleted() { if (pd != null && pd.isShowing()) { pd.dismiss(); } } @Override public void onError(Throwable e) { if (pd != null && pd.isShowing()) { pd.dismiss(); } } @Override public void onNext(RetrofitEntity retrofitEntity) { tvMsg.setText("无封装:\n" + retrofitEntity.getData().toString()); } @Override public void onStart() { super.onStart(); pd.show(); } } ); }可能你发现确是代码有点多,但是更加可怕的是,如果你一个activity或者fragment中多次需要http请求,你需要多次重复的写回调处理(一个回到就有4个方法呀!!!!反正我是忍受不了),而且以上处理还没有做过多的判断和错误校验就如此复杂!~好了介绍完了,开始咱们的优化之路吧!
<uses-permission android:name="android.permission.INTERNET"/>2.在app/build.gradle添加引用
/*rx-android-java*/ compile 'io.reactivex:rxjava:+' compile 'com.squareup.retrofit:adapter-rxjava:+' compile 'com.trello:rxlifecycle:+' compile 'com.trello:rxlifecycle-components:+' /*rotrofit*/ compile 'com.squareup.retrofit2:retrofit:+' compile 'com.squareup.retrofit2:converter-gson:+' compile 'com.squareup.retrofit2:adapter-rxjava:+' compile 'com.google.code.gson:gson:+'
/** * @api videoLink 50音图视频链接 * @url http://www.izaodao.com/Api/AppFiftyToneGraph/videoLink * @method post * @param once_no bool(选填,ture无链接) 一次性获取下载地址 * @return json array( * ret:1成功,2失败 * msg:信息 * data:{ * name:视频名称 * title:标题 * } )
String BASE_URL = " http://www.izaodao.com/Api/" Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build();2.设置接口service
/** * 接口地址 * Created by WZG on 2016/7/16. */ public interface MyApiEndpointInterface { @POST("AppFiftyToneGraph/videoLink") Call<RetrofitEntity> getAllVedio(@Body boolean once_no);
}
MyApiEndpointInterface apiService = retrofit.create(MyApiEndpointInterface.class); Call<RetrofitEntity> call = apiService.getAllVedio(true); call.enqueue(new Callback<RetrofitEntity>() { @Override public void onResponse(Response<RetrofitEntity> response, Retrofit retrofit) { RetrofitEntity entity = response.body(); Log.i("tag", "onResponse----->" + entity.getMsg()); } @Override public void onFailure(Throwable t) { Log.i("tag", "onFailure----->" + t.toString()); } });
@POST("AppFiftyToneGraph/videoLink") Observable<RetrofitEntity> getAllVedioBy(@Body boolean once_no);
Retrofit retrofit = new Retrofit.Builder() .client(builder.build()) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .baseUrl(HttpManager.BASE_URL) .build();3.回调交个rxjava去处理
HttpService apiService = retrofit.create(HttpService.class); Observable<RetrofitEntity> observable = apiService.getAllVedioBy(true); observable.subscribeOn(Schedulers.io()).unsubscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()) .subscribe( new Subscriber<RetrofitEntity>() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(RetrofitEntity retrofitEntity) { tvMsg.setText("无封装:\n" + retrofitEntity.getData().toString()); } } );
private volatile static HttpManager INSTANCE; //构造方法私有 private HttpManager() { //手动创建一个OkHttpClient并设置超时时间 OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS); Retrofit retrofit = new Retrofit.Builder() .client(builder.build()) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .baseUrl(BASE_URL) .build(); httpService = retrofit.create(HttpService.class); } //获取单例 public static HttpManager getInstance() { if (INSTANCE == null) { synchronized (HttpManager.class) { if (INSTANCE == null) { INSTANCE = new HttpManager(); } } } return INSTANCE; }1.2接口处理和回调处理:
/** * 处理http请求 * * @param basePar 封装的请求数据 */ public void doHttpDeal(BaseEntity basePar) { Observable observable = basePar.getObservable(httpService) .subscribeOn(Schedulers.io()) .unsubscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .map(basePar); observable.subscribe(basePar.getSubscirber()); }可以发现主要的封装都放入了BaseEntity中,我们跟着思路进入到BaseEntity
/** * 请求数据统一封装类 * Created by WZG on 2016/7/16. */ public abstract class BaseEntity<T> implements Func1<BaseResultEntity<T>, T> { /** * 设置参数 * * @param methods * @return */ public abstract Observable getObservable(HttpService methods); /** * 设置回调sub * * @return */ public abstract Subscriber getSubscirber();
@Override public T call(BaseResultEntity<T> httpResult) { if (httpResult.getRet() == 0) { throw new HttpTimeException(httpResult.getMsg()); } return httpResult.getData(); } }
/** * 自定义错误信息,统一处理返回处理 * Created by WZG on 2016/7/16. */ public class HttpTimeException extends RuntimeException { public static final int NO_DATA = 0x2; public HttpTimeException(int resultCode) { this(getApiExceptionMessage(resultCode)); } public HttpTimeException(String detailMessage) { super(detailMessage); } /** * 转换错误数据 * * @param code * @return */ private static String getApiExceptionMessage(int code) { String message = ""; switch (code) { case NO_DATA: message = "无数据"; break; default: message = "error"; break; } return message; } }
/** * 测试接口请求数据 * Created by WZG on 2016/7/16. */ public class SubjectPost extends BaseEntity { // 回调sub private Subscriber mSubscriber; private boolean all; public SubjectPost(Subscriber getTopMovieOnNext, boolean all) { this.mSubscriber = getTopMovieOnNext; this.all = all; } @Override public Observable getObservable(HttpService methods) { return methods.getAllVedioBys(all); } @Override public Subscriber getSubscirber() { return mSubscriber; } }
@POST("AppFiftyToneGraph/videoLink") Observable<BaseResultEntity<List<Subject>>> getAllVedioBys(@Body boolean once_no);
/** * 回调信息统一封装类 * Created by WZG on 2016/7/16. */ public class BaseResultEntity<T> { // 判断标示 private int ret; // 提示信息 private String msg; //显示数据(用户需要关心的数据) private T data;}
/** * 用于在Http请求开始时,自动显示一个ProgressDialog * 在Http请求结束是,关闭ProgressDialog * 调用者自己对请求数据进行处理 * Created by WZG on 2016/7/16. */ public class ProgressSubscriber<T> extends Subscriber<T> { // 回调接口 private HttpOnNextListener mSubscriberOnNextListener; // 弱引用反正内存泄露 private WeakReference<Context> mActivity; // 是否能取消请求 private boolean cancel; // 加载框可自己定义 private ProgressDialog pd; public ProgressSubscriber(HttpOnNextListener mSubscriberOnNextListener, Context context) { this.mSubscriberOnNextListener = mSubscriberOnNextListener; this.mActivity = new WeakReference<>(context); this.cancel = false; initProgressDialog(); } public ProgressSubscriber(HttpOnNextListener mSubscriberOnNextListener, Context context, boolean cancel) { this.mSubscriberOnNextListener = mSubscriberOnNextListener; this.mActivity = new WeakReference<>(context); this.cancel = cancel; initProgressDialog(); } /** * 初始化加载框 */ private void initProgressDialog() { Context context = mActivity.get(); if (pd == null && context != null) { pd = new ProgressDialog(context); pd.setCancelable(cancel); if (cancel) { pd.setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialogInterface) { onCancelProgress(); } }); } } } /** * 显示加载框 */ private void showProgressDialog() { Context context = mActivity.get(); if (pd == null || context == null) return; if (!pd.isShowing()) { pd.show(); } } /** * 隐藏 */ private void dismissProgressDialog() { if (pd != null && pd.isShowing()) { pd.dismiss(); } } /** * 订阅开始时调用 * 显示ProgressDialog */ @Override public void onStart() { showProgressDialog(); } /** * 完成,隐藏ProgressDialog */ @Override public void onCompleted() { dismissProgressDialog(); } /** * 对错误进行统一处理 * 隐藏ProgressDialog * * @param e */ @Override public void onError(Throwable e) { Context context = mActivity.get(); if (context == null) return; if (e instanceof SocketTimeoutException) { Toast.makeText(context, "网络中断,请检查您的网络状态", Toast.LENGTH_SHORT).show(); } else if (e instanceof ConnectException) { Toast.makeText(context, "网络中断,请检查您的网络状态", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(context, "错误" + e.getMessage(), Toast.LENGTH_SHORT).show(); Log.i("tag", "error----------->" + e.toString()); } dismissProgressDialog(); } /** * 将onNext方法中的返回结果交给Activity或Fragment自己处理 * * @param t 创建Subscriber时的泛型类型 */ @Override public void onNext(T t) { if (mSubscriberOnNextListener != null) { mSubscriberOnNextListener.onNext(t); } } /** * 取消ProgressDialog的时候,取消对observable的订阅,同时也取消了http请求 */ public void onCancelProgress() { if (!this.isUnsubscribed()) { this.unsubscribe(); } } }
/** * 成功回调处理 * Created by WZG on 2016/7/16. */ public interface HttpOnNextListener<T> { void onNext(T t); }
// 完美封装简化版 private void simpleDo() { SubjectPost postEntity = new SubjectPost(new ProgressSubscriber(simpleOnNextListener, this), true); HttpManager manager = HttpManager.getInstance(); manager.doHttpDeal(postEntity); } // 回调一一对应 HttpOnNextListener simpleOnNextListener = new HttpOnNextListener<List<Subject>>() { @Override public void onNext(List<Subject> subjects) { tvMsg.setText("已封装:\n" + subjects.toString()); } };