Retrofit2+Rxjava2之优雅的封装
来源:互联网 发布:软件项目管理目标 编辑:程序博客网 时间:2024/06/07 12:55
转载请说明出处
前言
这篇文章主要是教大家如何封装Retrofit2+Rxjava2,所以实现原理不做过多的解释,如有不付,额(你咬我呀!),
还有就是看这篇文章的同时,你一定要对 Retrofit2 和 Rxjava2 有所了解哦,不然懵逼了,我不负责哦,还有就是文章的开头用Retrofit2、和Rxjava2,是为了区分Retrofit1、和Rxjava1的版本为了后面更快的码字都用Retrofit、和Rxjava
亲,别着急,喝杯茶听我细细道来:
我们看看使用Retrofit+Rxjava需要哪些依赖(使用Android studio的小伙伴跟着我的脚步eclipse的兄弟看着办)
compile 'io.reactivex.rxjava2:rxjava:2.0.7' compile 'io.reactivex.rxjava2:rxandroid:2.0.1' compile 'com.squareup.retrofit2:retrofit:2.1.0' compile 'com.squareup.retrofit2:adapter-rxjava2:2.2.0' compile 'com.squareup.retrofit2:converter-gson:2.1.0' compile 'com.squareup.okhttp3:okhttp:3.5.0' compile 'com.squareup.okhttp3:logging-interceptor:3.6.0'
我们要知道Retrofit是基于OKhttp实现的,那么我们要写一个Retrofit工具,命名为RetrofitFactory
首先我们要创建一个 OKHttpClient对象
OkHttpClient mOkHttpClient=new OkHttpClient.Builder() .connectTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)//设置连接超时时间 .readTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)//设置读取超时时间 .writeTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS)//设置写入超时时间 .addInterceptor(InterceptorUtil.HeaderInterceptor())//添加其他拦截器 .addInterceptor(InterceptorUtil.LogInterceptor())//添加日志拦截器 .build();
为了代码的可读性我把拦截器提取到一个工具类为InterceptorUtil(不知道什么是拦截器的童鞋建议百度一下)里面有两个方法一个是答应日志拦截器的方法,一个是处理和拦截http请求的方法
package com.yr.example.http;import android.util.Log;import java.io.IOException;import okhttp3.Interceptor;import okhttp3.Request;import okhttp3.Response;import okhttp3.logging.HttpLoggingInterceptor;/** * @author yemao * @date 2017/4/9 * @description 拦截器工具类! */public class InterceptorUtil { public static String TAG="----"; //日志拦截器 public static HttpLoggingInterceptor LogInterceptor(){ return new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() { @Override public void log(String message) { Log.w(TAG, "log: "+message ); } }).setLevel(HttpLoggingInterceptor.Level.BODY);//设置打印数据的级别 } public static Interceptor HeaderInterceptor(){ return new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request mRequest=chain.request(); //在这里你可以做一些想做的事,比如token失效时,重新获取token //或者添加header等等,PS我会在下一篇文章总写拦截token方法 return chain.proceed(mRequest); } }; }}
Retrofit mRetrofit=new Retrofit.Builder() .baseUrl(HttpConfig.BASE_URL)//这个baseUrl是什么?比如一个接口为'http://baidu.com/xxx','http://baidu.com/'就可以为baseURL .addConverterFactory(GsonConverterFactory.create())//添加gson转换器 .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//添加rxjava转换器 .client(mOkHttpClient)//传入上面创建的OKHttpClient .build();
ok创建好Retrofit我们需要创建一个接口APIFunction类与之关联
package com.yr.example.http;import com.yr.example.http.bean.BaseEntity;import com.yr.example.http.config.URLConfig;import io.reactivex.Observable;import retrofit2.http.GET;import retrofit2.http.Query;/** * @author yemao * @date 2017/4/9 * @description API接口! */public interface APIFunction { }
终于可以看到我们完整的工具类RetrofitFactory了
package com.yr.example.http;import com.yr.example.http.config.HttpConfig;import java.util.concurrent.TimeUnit;import okhttp3.OkHttpClient;import retrofit2.Retrofit;import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;import retrofit2.converter.gson.GsonConverterFactory;/** * @author yemao * @date 2017/4/9 * @description 写自己的代码, 让别人说去吧! */public class RetrofitFactory { private static RetrofitFactory mRetrofitFactory; private static APIFunction mAPIFunction; private RetrofitFactory(){ OkHttpClient mOkHttpClient=new OkHttpClient.Builder() .connectTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS) .readTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS) .writeTimeout(HttpConfig.HTTP_TIME, TimeUnit.SECONDS) .addInterceptor(InterceptorUtil.HeaderInterceptor()) .addInterceptor(InterceptorUtil.LogInterceptor())//添加日志拦截器 .build(); Retrofit mRetrofit=new Retrofit.Builder() .baseUrl(HttpConfig.BASE_URL) .addConverterFactory(GsonConverterFactory.create())//添加gson转换器 .addCallAdapterFactory(RxJava2CallAdapterFactory.create())//添加rxjava转换器 .client(mOkHttpClient) .build(); mAPIFunction=mRetrofit.create(APIFunction.class); } public static RetrofitFactory getInstence(){ if (mRetrofitFactory==null){ synchronized (RetrofitFactory.class) { if (mRetrofitFactory == null) mRetrofitFactory = new RetrofitFactory(); } } return mRetrofitFactory; } public APIFunction API(){ return mAPIFunction; }}
接下来我们就要开始接口了哦,回到我们上面的APIFunction接口模拟一个API接口getBaidu()因为上面我们已经对Retrofit和APIFunction进行关联了可以返回得到一个observable<Object>(终于轮到Rxjava出场了)
package com.yr.example.http;import com.yr.example.http.bean.BaseEntity;import com.yr.example.http.config.URLConfig;import io.reactivex.Observable;import retrofit2.http.GET;import retrofit2.http.Query;/** * @author yemao * @date 2017/4/9 * @description API接口! */public interface APIFunction { @GET(URLConfig.baidu_url) Observable<Object> getBaidu(@Query("wd")String name);}
额看到这里我们怎么让它返回一个对象实体,不能让它返回我们想要的实体类吗,答案是yes,OK那我们来封装一个BaseEntity
当然我这只是举例个例子,很有可能大家的返回参数不是按照下面的,(因实际情况做修改)
package com.yr.example.http.bean;/** * @author yemao * @date 2017/4/9 * @description 解析实体基类! */public class BaseEntity<T> { private static int SUCCESS_CODE=42440;//成功的code private int code; private String msg; private T data; public boolean isSuccess(){ return getCode()==SUCCESS_CODE; } 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; }}
我们看看修改过后的接口是怎么样的
@GET(URLConfig.baidu_url) Observable<BaseEntity<Object>> getBaidu(@Query("wd")String name);
当然这是候的Object可以换为你想要的实体比如(前提是你要知道返回的数据类型我这只是打个比方)
package com.yr.example.http.bean;/** * @author yemao * @date 2017/4/9 * @description 写自己的代码, 让别人说去吧! */public class ABean { private String name; private String pwd; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPwd() { return pwd; } public void setPwd(String pwd) { this.pwd = pwd; }}
把object替换为ABean
@GET(URLConfig.baidu_url) Observable<BaseEntity<ABean>> getBaidu(@Query("wd")String name);
OK这时候就可以跑通了让我们看看完整的请求 (observable(被观察者)和observer(观察者)相订阅)
RetrofitFactory.getInstence().API() .getBaidu("我是中国人") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Observer<BaseEntity<ABean>>() { @Override public void onSubscribe(Disposable d) { } @Override public void onNext(BaseEntity<ABean> aBeanBaseEntity) { } @Override public void onError(Throwable e) { } @Override public void onComplete() { } });
可以发现还有地方可以优化比如Observable线程的切换,以及Observer的封装,不废话了我们先封装一个BaseObserver
BaseObserver实现了Observer接口,然后添加了5个方法
onRequestStart 请求开始时调用
onRequestEnd 请求结束时调用
onFailure 请求失败时调用
onSuccees 请求成功时调用
onCodeError 请求成功但code码错误时调用
然后完整的BaseObserve
package com.yr.example.http.base;import android.accounts.NetworkErrorException;import android.content.Context;import android.util.Log;import com.yr.example.http.bean.BaseEntity;import com.yr.example.widget.ProgressDialog;import java.net.ConnectException;import java.net.UnknownHostException;import java.util.concurrent.TimeoutException;import io.reactivex.Observer;import io.reactivex.disposables.Disposable;/** * @author yemao * @date 2017/4/9 * @description 写自己的代码, 让别人说去吧! */public abstract class BaseObserver<T> implements Observer<BaseEntity<T>> { protected Context mContext; public BaseObserver(Context cxt) { this.mContext = cxt; } public BaseObserver() { } @Override public void onSubscribe(Disposable d) { onRequestStart(); } @Override public void onNext(BaseEntity<T> tBaseEntity) { onRequestEnd(); if (tBaseEntity.isSuccess()) { try { onSuccees(tBaseEntity); } catch (Exception e) { e.printStackTrace(); } } else { try { onCodeError(tBaseEntity); } catch (Exception e) { e.printStackTrace(); } } } @Override public void onError(Throwable e) {// Log.w(TAG, "onError: ", );这里可以打印错误信息 onRequestEnd(); try { if (e instanceof ConnectException || e instanceof TimeoutException || e instanceof NetworkErrorException || e instanceof UnknownHostException) { onFailure(e, true); } else { onFailure(e, false); } } catch (Exception e1) { e1.printStackTrace(); } } @Override public void onComplete() { } /** * 返回成功 * * @param t * @throws Exception */ protected abstract void onSuccees(BaseEntity<T> t) throws Exception; /** * 返回成功了,但是code错误 * * @param t * @throws Exception */ protected void onCodeError(BaseEntity<T> t) throws Exception { } /** * 返回失败 * * @param e * @param isNetWorkError 是否是网络错误 * @throws Exception */ protected abstract void onFailure(Throwable e, boolean isNetWorkError) throws Exception; protected void onRequestStart() { } protected void onRequestEnd() { closeProgressDialog(); } public void showProgressDialog() { ProgressDialog.show(mContext, false, "请稍后"); } public void closeProgressDialog() { ProgressDialog.cancle(); }}
然后我们看看完整的请求
RetrofitFactory.getInstence().API() .getBaidu("我是中国人") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new BaseObserver<ABean>() { @Override protected void onSuccees(BaseEntity<ABean> t) throws Exception { } @Override protected void onFailure(Throwable e, boolean isNetWorkError) throws Exception { } });
是不是少了许多代码,最后我们将线程切换提成一个方法,放在一个新建的baseActivity里面让所有activity都继承自它,就都可以拿到这个方法了
package com.yr.example.common;import android.support.v4.app.FragmentActivity;import io.reactivex.Observable;import io.reactivex.ObservableSource;import io.reactivex.ObservableTransformer;import io.reactivex.android.schedulers.AndroidSchedulers;import io.reactivex.schedulers.Schedulers;/** * @author yemao * @date 2017/4/9 * @description 写自己的代码, 让别人说去吧! */public class BaseActivity extends FragmentActivity { public <T> ObservableTransformer<T,T> setThread(){ return new ObservableTransformer<T,T>() { @Override public ObservableSource<T> apply(Observable<T> upstream) { return upstream.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()); } }; }}
最后看看完成的请求
package com.yr.example;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import com.yr.example.common.BaseActivity;import com.yr.example.http.RetrofitFactory;import com.yr.example.http.base.BaseObserver;import com.yr.example.http.bean.ABean;import com.yr.example.http.bean.BaseEntity;import io.reactivex.Observer;import io.reactivex.android.schedulers.AndroidSchedulers;import io.reactivex.disposables.Disposable;import io.reactivex.schedulers.Schedulers;public class MainActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); getData(); } public void getData() { RetrofitFactory.getInstence().API() .getBaidu("我是中国人") .compose(this.<BaseEntity<ABean>>setThread()) .subscribe(new BaseObserver<ABean>() { @Override protected void onSuccees(BaseEntity<ABean> t) throws Exception { } @Override protected void onFailure(Throwable e, boolean isNetWorkError) throws Exception { } }); }}
还有两个config类我就不贴了,没什么技术含量,随后我会在文章的结尾demo下载地址
那么到这里,封装基本上大功告成了,但是上面例子并不能成功解析,因为我调用的百度的搜索接口,返回的是XML,不过拿去真实的服务器请求是完全没有问题的哦
最后贴一下项目目录结构
GitHub项目地址:点击打开链接https://git.oschina.net/yrmao/retrofit2_rxjava2-android
- Retrofit2+Rxjava2之优雅的封装
- RxJava2 + Retrofit2 优雅简洁封装
- Retrofit2+Rxjava2联网的封装
- 优雅地封装使用rxjava2+retrofit2发送http请求
- 非常简易的Rxjava2+Retrofit2封装
- Rxjava2和Retrofit2网络库的封装
- Retrofit2+Rxjava2网络请求框架的封装
- retrofit2+rxjava2封装解析
- 简单封装retrofit2+rxjava2
- Rxjava2+okhttp3+Retrofit2封装
- Android 优雅的让RxJava2.0+Retrofit2.0结合使用
- Android 优雅的让RxJava2.0+Retrofit2.0结合使用
- 给你一个原汁原味的Retrofit2+Rxjava2的请求封装
- 简单实现RxJava2+Okhttp+Retrofit2的网络请求框架封装
- Mvp+Retrofit2+RxJava2 项目中使用的简洁封装
- Mvp+Retrofit2+RxJava2 项目中使用的简洁封装
- rxjava2 结合retrofit2进行业务封装
- 1、RxJava2 & Retrofit2封装实践 简介
- systemd学习小结
- 2017-4-8蓝桥杯总结(1) 结果填空部分
- spring AOP切面,注解实现,获取参数
- POJ NOI0113-01 数制转换(Bailian2710)
- SVN在Android studio中的使用
- Retrofit2+Rxjava2之优雅的封装
- POJ NOI0113-02 不吉利日期(Bailian2723)
- Android SQLite (一) 数据库简介
- Android SQLite (二) 基本用法
- Android SQLite (三 ) 全面详解(一)
- Android SQLite (四 ) 全面详解(二)
- CentOS7安装ifconfig
- Android SQLite (五 ) 全面详解(三)
- 用git上传项目到GitHub