在这Rx流行的时代,我也接触一段时间了,便通过这篇文章记录下Retrofit 2 + RxAndroid的一些实践记录(这里记录客户端网络请求的实践)。
定义Response基类
根据接口返回响应结果定义一个BaseRes类。
我接口返回的数据格式如下:
BaseRes定义如下,需对应。
public class BaseRes<T> {
public int showapi_res_code;
public String showapi_res_error;
public T showapi_res_body;
}
定义Service Method
public interface ApiService {
/** * 获取笑话列表
*
* @return
*/
@GET("showapi_open_bus/showapi_joke/joke_text")
Observable<BaseRes<JokeInfo>> getJokes(@Query("page") int page);
}
其中JokeInfo是BaseRes中泛型的具体实现,是根据获取的数据具体定义的(看后面demo上)
创建Retrofit实例,并创建Service Method
根据需要定义OkHttpClient,然后实例Retrofit,并创建Service Method。
public class ApiClient {
public static final String BASE_URL = "http://apis.baidu.com/";
private static Retrofit mRetrofit;
private static OkHttpClient.Builder mClientBuilder;
public ApiService mApiService;
static {
mClientBuilder = new OkHttpClient.Builder();
/** *设置缓存,代码略 */
/** *公共参数,代码略 */
/** * 设置头,代码略 */
/** * Log信息拦截器,代码略 */
/** * 设置cookie,代码略 */
/** * 设置超时和重连,代码略 */
}
private ApiClient() {
mRetrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.client(mClientBuilder.build())
.build();
mApiService = mRetrofit.create(ApiService.class);
}
//在访问HttpMethods时创建单例
private static class SingletonHolder {
private static final ApiClient INSTANCE = new ApiClient();
}
//获取单例
public static ApiClient getInstance() {
return SingletonHolder.INSTANCE;
}
}
线程调度管理
基本我们都是在io上发请求,在主线程上处理响应和界面交互,所以定义一个默认的线程调度类(当然为了更好的处理,io线程也可以自己定义,这里使用默认的Schedulers.io())。
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<>();
}
}
封装Subscriber
为了统一处理错误和一些加载效果之类的操作,定义BaseSubscriber和LoadingSubscriber对Subscriber封装。
public abstract class BaseSubscriber<T extends BaseRes> extends Subscriber<T> {
private Context mContext;
public BaseSubscriber() {
}
public BaseSubscriber(Context context) {
mContext = context;
}
public Context getContext() {
return mContext;
}
@Override
public void onCompleted() {
}
@CallSuper
@Override
public void onError(Throwable e) {
/** 根据异常处理错误信息 */
ToastUtil.showShort(getContext(), NetworkUtils.getMsgByError(e));
}
@Override
public void onNext(T t) {
if (t.showapi_res_code == Const.CODE_SUCCESS) {
_onNext(t);
} else {
ToastUtil.showShort(mContext, t.showapi_res_error);
}
}
public abstract void _onNext(T entity);
}
LoadingSubscriber继承BaseSubscriber,然后重写OnStart(),onCompleted(),onError()方法,再自己去处理逻辑,这里就不贴代码了,当然,如果还需其他统一处理也可以类似去实现自己想要的Subscriber,比如DialogSubscriber。
使用
这里我通过百度api上的易源_笑话大全接口作为例子说明使用Retrofit + RxAndroid实现请求网络并在界面上展现。
1、定义笑话类JokeInfo
代码有点长,就不贴出来了,看后面链接上的Demo。
2、MVP实现获取数据
首先定义一个契约接口统一管理该模块的Presenter,Model,View。
public interface InfoContract {
interface Model extends BaseModel {
Observable<BaseRes<JokeInfo>> getJokes(int page);
}
interface View extends BaseView {
void loadList(List<JokeInfo.JokeContent> jokeContents, int pageCount);
}
abstract class Presenter extends BasePresenter<Model, View> {
public abstract void getJokes(int page);
@Override
public void onStart() {
}
}
}
(这里的BaseModel,BaseView,BasePresenter看Demo)
定义Model继承InfoContract.Model,返回Observable,然后在InfoPresenter中订阅。
public class InfoModel implements InfoContract.Model {
@Override
public Observable<BaseRes<JokeInfo>> getJokes(int page) {
return ApiClient.getInstance().mApiService
.getJokes(page)
.compose(SchedulerTransformer.<BaseRes<JokeInfo>>create());
}
}
public class InfoPresenter extends InfoContract.Presenter {
@Override
public void getJokes(int page) {
mRxManage.add(mModel.getJokes(page)
.subscribe(new LoadingSubscriber<BaseRes<JokeInfo>>(mContext) {
@Override
public void _onNext(BaseRes<JokeInfo> entity) {
mView.loadList(entity.showapi_res_body.getContentlist(),
entity.showapi_res_body.getAllPages());
}
}));
}
}
3、界面上实现
在onCreate里面初始化MVP
mPresenter = new InfoPresenter();
mModel = new InfoModel();
mPresenter.setVM(mModel, this, this); // 第一个this是回调View,第二个this是Context
在需要获取数据的地方执行
mPresenter.getJokes(page);
进行获取数据。
在View回调上处理返回的数据,并展现到界面上。
总结
通过以上实践,是否发现Retrofit + RxAndroid 大大改善了代码的可维护性,代码逻辑清晰了然。
网友评论