RxJava + Retrofit2.0的项目实战完美封装
来源:互联网 发布:网络飞机票怎么取登机 编辑:程序博客网 时间:2024/06/06 11:35
Retrofit 和RxJava已经出来很久了,从去年开始rxjava和retrofit就开始火,所以之前在做项目的时候也用了rxjava和retrofit,今天就介绍一下在项目中如何封装rxjava和retrofit。对于 RxJava 不是很了解的同学推荐你们看这篇文章给 Android 开发者的 RxJava 详解。Retrofit的使用可以看看Android Retrofit 2.0使用。
首先在我们的工程的build.gradle中添加依赖:
compile 'io.reactivex:rxjava:1.1.8' compile 'io.reactivex:rxandroid:1.2.1' compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0' compile 'com.squareup.retrofit2:converter-gson:2.1.0'
然后封装retrofit:
public class HttpMethods { //接口根地址 public static final String BASE_URL = "http://www.baidu.com"; //设置超时时间 private static final long DEFAULT_TIMEOUT = 10_000L; private Retrofit retrofit; private OkHttpClient client; private static class SingletonHolder { private static final HttpMethods INSTANCE = new HttpMethods(); } //私有化构造方法 private HttpMethods() { client = new OkHttpClient.Builder() .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS) //添加请求头 //.addInterceptor(new HeaderInterceptor()) //添加日志打印拦截器 .addInterceptor(new LoggerInterceptor("===", true)) .build(); retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .client(client) //添加Gson解析 .addConverterFactory(GsonConverterFactory.create()) //添加rxjava .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); } public static HttpMethods getInstance() { return SingletonHolder.INSTANCE; } //这里返回一个泛型类,主要返回的是定义的接口类 public <T> T createService(Class<T> clazz) { return retrofit.create(clazz); }}
这就是定义的接口类:
/** * 接口定义 */public interface ApiService { @FormUrlEncoded @POST("/sys/sendMsg") Observable<BaseEntity<DataEntity>> getData(@FieldMap Map<String, String> params);}
这里的根地址和接口中的地址都是随便写的一个地址,用的时候替换成自己项目的地址就行了。添加请求头的话,由于项目中没用到所以直接注释了。
接下来就是封装服务器请求和返回数据。一般情况下返回的数据结构是这样的:
{ "status_code":10000, "error_msg":"请求成功!", "data":{ "name":"张三", "age":3 }}
如果你们的服务器返回不是这样的格式那你就只有坐下来请他喝茶,跟他好好说了。大不了就怼他。
对于这样的数据我们肯定要对status_code做出一些判断,不同的status_code对应不同的错误信息。所以我们新建一个BaseEntity,对应上面的数据结构。
public class BaseEntity<T> implements Serializable { private int status_code; private String error_msg; private T data; public T getData() { return data; } public void setData(T data) { this.data = data; } public int getStatus_code() { return status_code; } public void setStatus_code(int status_code) { this.status_code = status_code; } public String getError_msg() { return error_msg; } public void setError_msg(String error_msg) { this.error_msg = error_msg; }}
这就是所有实体的一个基类,data可以为任何数据类型,所以我们使用泛型。
我们要对所以返回结果进行预处理,新建一个DefaultTransformer继承Observable.Transformer,预处理无非就是对status_code进行判断和解析,不同的错误返回不同的错误信息。有个操作符compose。因为我们在每一个请求中都会处理status_code以及使用一些操作符,比如用observeOn和subscribeOn来切换线程。RxJava提供了一种解决方案:Transformer(转换器),一般情况下就是通过使用操作符compose()来实现。
代码:
public class DefaultTransformer<T> implements Observable.Transformer<T, T> { @Override public Observable<T> call(Observable<T> tObservable) { return tObservable .subscribeOn(Schedulers.io()) .unsubscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .map(new Func1<T, T>() {// 通用错误处理,判断code @Override public T call(T t) { if (((BaseEntity<T>)t).getStatus_code() != 10000) { throw new ApiException(((BaseEntity<T>)t).getStatus_code(), ((BaseEntity<T>)t).getError_msg()); } return t; } }); } public static <T> DefaultTransformer<T> create() { return new DefaultTransformer<>(); }}
这里我们使用map操作符把Obserable< BaseEntity< T > >,转换成为Observable< T >在内部对status_code进行了预处理。这里当状态码不等于10000就表示请求出错抛出异常。这里的ApiException是我们自定义的一个异常类,用来处理服务器返回的异常。
代码:
public class ApiException extends IllegalArgumentException { private int code; public ApiException(int code, String msg) { super(msg); this.code = code; } public int getCode() { return code; }}
接下来就是处理网络请求的操作,和显示加载等待的dialog:
public abstract class ApiSubscriber<T> extends Subscriber<T> { private LoadingDialog mDialog; public ApiSubscriber() { } public ApiSubscriber(@NonNull Context context) { mDialog = new LoadingDialog(context); } @Override public void onStart() { if (mDialog != null) mDialog.show(); } @Override public void onCompleted() { if (mDialog != null && mDialog.isShowing()) mDialog.dismiss(); } /** * 只要链式调用中抛出了异常都会走这个回调 */ @Override public void onError(Throwable e) { if (mDialog != null && mDialog.isShowing()) mDialog.dismiss(); if (e instanceof ApiException) { //处理服务器返回的错误 } else if (e instanceof ConnectException || e instanceof UnknownHostException) { ToastUtils.showShort("网络异常,请检查网络"); } else if (e instanceof TimeoutException || e instanceof SocketTimeoutException) { ToastUtils.showShort("网络不畅,请稍后再试!"); } else if (e instanceof JsonSyntaxException) { ToastUtils.showShort("数据解析异常"); } else { ToastUtils.showShort("服务端错误"); } e.printStackTrace(); }}
这里新建一个ApiSubscriber类继承Subscriber类,写了两个构造方法,一个是显示dialog,一个是不显示dialog。重写了三个方法,这里我们没有重写onNext方法,因为这个方法是请求成功返回数据的,所以我们等到请求数据界面去重写。在onError里面做了所有的错误处理,在里面可以根据服务器返回的错误码对不同的错误做不同的处理。
接下来的话就是管理生命周期了。有个专门的库可以管理生命周期的叫RxLifecycle,可以去看看。不过我们不用这个,我们在BaseActivity里面写。
public abstract class BaseActivity extends AppCompatActivity { private CompositeSubscription mCompositeSubscription; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override protected void onDestroy() { super.onDestroy(); onUnsubscribe(); } /** * 所有rx订阅后,需要调用此方法,用于在detachView时取消订阅 */ protected void addSubscription(Subscription subscribe) { if (mCompositeSubscription == null) mCompositeSubscription = new CompositeSubscription(); mCompositeSubscription.add(subscribe); } /** * 取消本页面所有订阅 */ protected void onUnsubscribe() { if (mCompositeSubscription != null && mCompositeSubscription.hasSubscriptions()) { mCompositeSubscription.unsubscribe(); } }}
我们在请求数据的地方调用addSubscription(Subscription subscribe)方法,当activity在onDestroy()的时候就取消订阅了。
最后就是我们的请求数据了,这是之前定义的一个伪接口:
public interface ApiService { @FormUrlEncoded @POST("/sys/sendMsg") Observable<BaseEntity<DataEntity>> getData(@FieldMap Map<String, String> params);}
然后我们在activity里面这样写:
public class MainActivity extends BaseActivity { private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView) findViewById(R.id.tv_content); findViewById(R.id.btn_request).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { getData(); } }); } private void getData() { Map<String, String> params = new HashMap<>(); params.put("user_name", ""); params.put("user_pwd", ""); Subscription subscribe = HttpMethods.getInstance() .createService(ApiService.class) .getData(params) .compose(DefaultTransformer.<BaseEntity<DataEntity>>create()) .subscribe(new ApiSubscriber<BaseEntity<DataEntity>>(this) { @Override public void onNext(BaseEntity<DataEntity> entity) { } }); addSubscription(subscribe);//添加订阅 }}
在onNext方法里面就能获取到我们的数据了,当然这个接口是请求不成功的,在使用的时候替换成自己的接口就行了。retrofit还有很多的注解,这里只是使用了@FormUrlEncoded注解(表单的形式)做个示例。到这里封装就基本完成了,我也是菜鸟,希望大家多提意见,互相学习。
源码地址
- RxJava + Retrofit2.0的项目实战完美封装
- Android基于Retrofit2.0 封装的超好用的RetrofitClient工具类(完美结合RxJava)
- Retrofit2-RxJava-Dagger2-MVP完美封装
- retrofit2.0+okhttp3+rxjava的封装(简单好用)
- Android-->Rxjava与Retrofit2的结合实战
- Okhttp3+Rxjava+Retrofit2封装
- Novate 网络库:Retrofit2.0和RxJava的又一次完美改进加强(Tamic博客 -CSDN)
- Retrofit2+Rxjava学习到封装
- retrofit2+okhttp3+rxjava网络封装
- Android基于Retrofit2.0 +RxJava 封装的超好用的RetrofitClient工具类(六)
- Retrofit+RxJava 完美封装
- RxJava和Retrofit2.0的结合使用
- RxJava前奏之Retrofit2.0的学习
- Retrofit2.0+RxJava+MVP+Bmob的使用
- Android RxJava+Retrofit2.0+MVP的小试牛刀
- Retrofit2+Rxjava练手项目_1
- Retrofit2.0以及rxjava
- Android实战——Retrofit2的使用和封装
- 如何实现CSDN打赏功能
- 【python】Matplotlib画图(一)——散点图scatter
- 关于MySQL远程连接的一些小问题
- Redis应用场景
- 操作系统基础知识
- RxJava + Retrofit2.0的项目实战完美封装
- String.intern()详解,关于String s2 = new String("ja") + new String("va"); s2.intern();
- intelliJ idea运行新的test功能时,报错:class not found "....." empty test suite
- 事件分发拦截消费源码解读
- 【Java】clone
- 深入理解const
- 解决方案:webview部分内容不显示的问题,或者无法跳转
- 写一个方法,实现字符串的反转,如:输入abc,输出cba
- AutoLayout的各种使用方法