对RxJava与Retrofit不了解的朋友需要优先进主页或者本人写的系统导读
Rxjava
RxAndroid
Retrofit
RxJava2.x的集成及用法详解
Retrofit2使用教程
RxJava2+Retrofit2结合使用
其实啊这些功能实现起来都不难,最重要的还是思想,看你想怎么玩,好啦,学习之前先来看看优化前后的区别,学习起来更有劲儿了是吧
优化前调用
//创建日志拦截器
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);//设定日志级别
//创建OkHttpClient
OkHttpClient mOkHttpClient = new OkHttpClient.Builder()
.connectTimeout(ApiService.HTTP_TIME, TimeUnit.SECONDS)
.readTimeout(ApiService.HTTP_TIME, TimeUnit.SECONDS)
.writeTimeout(ApiService.HTTP_TIME, TimeUnit.SECONDS)
.addInterceptor(httpLoggingInterceptor)//添加拦截器
.build();
//创建Retrofit
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiService.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.client(mOkHttpClient)
.build();
//创建接口实现类
ApiService apiService = retrofit.create(ApiService.class);
Observable callHome = apiService.getCallHome(getString(R.string.phone_num), getString(R.string.phone_key));
callHome
.subscribeOn(Schedulers.io())
.map(new Function() {
@Override
public String apply(CallHomeBean callHomeBean) throws Exception {
return callHomeBean.getResult().getProvince() + callHomeBean.getResult().getCity();
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer() {
@Override
public void accept(String s) throws Exception {
tvPhone.setText(s);
}
});
优化后调用
RetrofitFactory
.getInstence()
.getPhoneInfo(getString(R.string.phone_location), getString(R.string.phone_key),new BaseObserver() {
@Override
protected void onSuccees(BaseEntity t){
tvPhone.setText(t.getResult().getProvince());
}
@Override
protected void onFailure(Throwable e, boolean isNetWorkError){
tvPhone.setText(e.getMessage());
}
});
这里可以看到只是实例化了一个单例的RetrofitFactory,调用了一个方法。想必大家已经知道代码去哪了
public class RetrofitFactory {
private final ApiService mApiService;
private static RetrofitFactory mRetrofitFactory;
private RetrofitFactory() {
//创建日志拦截器
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);//设定日志级别
//创建OkHttpClient
OkHttpClient mOkHttpClient = new OkHttpClient.Builder()
.connectTimeout(ApiService.HTTP_TIME, TimeUnit.SECONDS)
.readTimeout(ApiService.HTTP_TIME, TimeUnit.SECONDS)
.writeTimeout(ApiService.HTTP_TIME, TimeUnit.SECONDS)
.addInterceptor(httpLoggingInterceptor)//添加拦截器
.build();
//创建Retrofit
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiService.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())//添加gson转换器
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//添加rxjava2转换器
.client(mOkHttpClient)
.build();
//创建接口实现类
mApiService = retrofit.create(ApiService.class);
}
// 懒汉式单例模式
public static RetrofitFactory getInstence() {
if (mRetrofitFactory == null) {
// 静态方法,使用当前类本身充当进程锁
synchronized (RetrofitFactory.class) {
if (mRetrofitFactory == null)
mRetrofitFactory = new RetrofitFactory();
}
}
return mRetrofitFactory;
}
//请求网络的API接口类
public ApiService API() {
return mApiService;
}
//构建API接口实现方法
public void getPhoneInfo(String phone, String key, BaseObserver scheduler) {
API()
.getPhoneMsg(phone, key)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(scheduler);
}
//构建API接口实现方法
public void getWeatherInfo(Map map, BaseObserver scheduler) {
API()
.getWeather(map)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(scheduler);
}
}
RetrofitFactory主要负责创建具体Retrofit、调度分发请求、设置格式工厂、构建OkHttpClient、构建日志拦截器、构建Retrofit的接口service。
那么有的朋友可能发现了在指定生产线程和消费线程的时候,步骤有点麻烦,每个api都得进行指定线程,那么可以利用rxJava的转换器写一个Transformer
public ObservableTransformer threadTransformer() {
return new ObservableTransformer() {
@Override
public ObservableSource apply(Observable observable) {
return observable
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
};
}
那么再次调用的时候就变成了这样
public void getPhoneInfo(String phone, String key, BaseObserver<PhoneInfo> scheduler) {
API()
.getPhoneMsg(phone, key)
.compose(threadTransformer())
.subscribe(scheduler);
}
public void getWeatherInfo(Map<String ,String> map, BaseObserver<WeatherInfo> scheduler) {
API()
.getWeather(map)
.compose(threadTransformer())
.subscribe(scheduler);
}
这里可以看到最后一个形参并不是普通的Observer,而是一个经过二次封装的对象,接着往下看
public abstract class BaseObserver<T> implements Observer<BaseEntity<T>> {
private static final String TAG = BaseObserver.class.getSimpleName();
private Context mContext;
protected BaseObserver(){ }
protected BaseObserver(Context context) { this.mContext = context; }
@Override
public void onNext(BaseEntity tBaseEntity) {
if (tBaseEntity.isSuccess()) {
try {
onSuccees(tBaseEntity);
} catch (Exception e) {
e.printStackTrace();
}
} else {
try {
onCodeError(tBaseEntity.getError_code());
onError(new Throwable(tBaseEntity.getReason()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void onError(Throwable e) {
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() { }
@Override
public void onSubscribe(Disposable d) { }
/**
* 返回成功
*
* @param data
* @throws Exception
*/
protected abstract void onSuccees(BaseEntity data) throws Exception;
/**
* 返回失败
*
* @param e
* @param isNetWorkError 是否是网络错误
* @throws Exception
*/
protected abstract void onFailure(Throwable e, boolean isNetWorkError) throws Exception;
/**
* 返回成功了,但是code错误
*
* @param error
* @throws Exception
*/
protected void onCodeError(int error) throws Exception { }
可以看出BaseObserver只做了三件事:采用适配器模式对Observer抽象方法重新封装、统一处理网络的异常、通过泛型限定了实例类的类型BaseEntity<\T>。最后再看看BaseEntity干了些啥
public class BaseEntity {
private static int SUCCESS_CODE = 0;//成功的code
private String reason;//请求成功或失败描述
private int error_code;//错误码
private T result;//数据集
public boolean isSuccess() {
return getError_code() == SUCCESS_CODE;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public T getResult() {
return result;
}
public void setResult(T result) {
this.result = result;
}
public int getError_code() {
return error_code;
}
public void setError_code(int error_code) {
this.error_code = error_code;
}
}
通常服务器端会返回统一的数据格式,只是数据略有区分,BaseEntity的作用就是抽取数据中的公共属性,例如:
/**
* @description 此json只有中间result的内容不同其他都相同,所以可抽取的属性包括:
* resultcode、reason、error_code和外层的result
*/
1. { 2. {
"resultcode":"200", "resultcode":"200",
"reason":"Return Successd!", "reason":"Return Successd!",
"result":{ "result":{
"province":"浙江", "temp": "21", /*当前温度*/
"city":"杭州", "wind_direction": "西风", /*当前风向*/
"areacode":"0571", "wind_strength": "2级", /*当前风力*/
"zip":"310000", "humidity": "4%", /*当前湿度*/
"company":"中国移动", "time": "14:25" /*更新时间*/
"card":""
}
"error_code": 0 }
"error_code": 0
} }
/**
* 测试接口使用的是聚合数据提供的免费API
* 地址:https://www.juhe.cn/
*/
public interface ApiService {
// 用Retrofit需要后台接口遵循REST风格的请求
// 请求示例:http://apis.juhe.cn/mobile/get?phone=1351103&key=您申请的KEY
// 基本地址:http://apis.juhe.cn
// 功能地址:/mobile/get
// 请求参数:?phone=1351103&key=790c971125********190725627e5ca5
String BASE_URL = "http://apis.juhe.cn/";
//网络请求时长
int HTTP_TIME = 5000;
/**
* 接口1:获取来电归属地, API一定是以 "/" 开头,这是Retrofit规范
*/
@GET("mobile/get")
Observable> getPhoneMsg(@Query("phone") String phone, @Query("key") String key);
/**
* 接口2:获取天气信息
*/
@GET("/weather/index")
Observable> getWeather(@QueryMap Map options);
}
请求网络的API接口类,这里你可以增加你需要的请求接口,例如json数据的请求啊、单个或多个图片、文件的上传下载等等。
Demo下载传送门