Mvp+Rxjava+Retrofit2.0+Okhttp完善版
2018-12-27 本文已影响7人
奔跑吧李博
这个框架在项目的使用中已经有好一段时间了,于是把其中基本的模块抽取出来写出来。
demo结构图:
搭建流程:
引入所需依赖库:
//Rxjava
implementation 'io.reactivex:rxjava:1.1.0'
implementation 'io.reactivex:rxandroid:1.1.0'
//Retrofit
implementation 'com.squareup.retrofit2:retrofit:2.0.0-beta4'
implementation 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'
implementation 'com.squareup.retrofit2:adapter-rxjava:2.0.0-beta4'
//Gson
implementation 'com.google.code.gson:gson:2.6.2'
使用Retrofit+Rxjava
1.请求接口地址以及声明类:
功能是初始化retrofit和okhttp;设置okhttp的header拦截器、请求数据拦截器、请求缓存拦截器。
public interface ApiService {
/** 正式服务器地址 */
String SERVER_ADDRESS_RELEASE = "";
/** 测试服务器地址 */
String SERVER_ADDRESS_DEBUG = "";
/** 服务器域名 */
String SERVER_ADDRESS = isDebug ? SERVER_ADDRESS_DEBUG : SERVER_ADDRESS_RELEASE;
@GET("")
Observable<BaseModel<VideoBean>> getVideoData();
}
2.单例的Retrofit和Okhttp管理类
单例模式创建ApiService类,添加服务器地址,设置5秒请求超时。ApiService默认返回Call类型,但是需要直接转化Observable类型,此时需要添加addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 。需要直接转化为需要的实体类,需要添加addCallAdapterFactory(RxJavaCallAdapterFactory.create())
public class ApiManager {
private static ApiManager mApiManager;
private OkHttpClient mOkHttpClient;
private static ApiService mApiService;
private final int TIMEOUT = 10;
private ApiManager() {
initOkhttp();
initRetrofit();
}
public static synchronized ApiService getApiService() {
if (mApiService == null) {
mApiManager = new ApiManager();
}
return mApiService;
}
private void initOkhttp() {
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(TIMEOUT, TimeUnit.SECONDS) //连接超时设置
.readTimeout(TIMEOUT, TimeUnit.SECONDS) //写入缓存超时10s
.writeTimeout(TIMEOUT, TimeUnit.SECONDS) //读取缓存超时10s
.retryOnConnectionFailure(true) //失败重连
.addInterceptor(new HeaderInterceptor()) //添加header
.addInterceptor(new NetCacheInterceptor()); //添加网络缓存
addLogIntercepter(builder); //日志拦截器
setCacheFile(builder); //网络缓存
mOkHttpClient = builder.build();
}
private void initRetrofit() {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiService.SERVER_ADDRESS)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(mOkHttpClient)
.build();
mApiService = retrofit.create(ApiService.class);
}
/**
* 设置缓存文件路径
*/
private void setCacheFile(OkHttpClient.Builder builder) {
//设置缓存文件
File cacheFile = new File(DirConfig.HTTP_CACHE);
//缓存大小为10M
int cacheSize = 10 * 1024 * 1024;
Cache cache = new Cache(cacheFile,cacheSize);
builder.cache(cache);
}
/**
* 调试模式下加入日志拦截器
* @param builder
*/
private void addLogIntercepter(OkHttpClient.Builder builder) {
if (AppConfig.isDebug) {
builder.addInterceptor(new LoggingInterceptor());
}
}
}
3.给okhttp添加拦截器
- 统一添加header的拦截器:
public class HeaderInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request.Builder builder = chain.request().newBuilder();
builder.addHeader("token", UserInfoCache.TOKEN);
return chain.proceed(builder.build());
}
}
- Okhttp返回数据日志拦截器:
public class LoggingInterceptor implements Interceptor {
private final int byteCount = 1024*1024;
@Override
public Response intercept(Chain chain) throws IOException {
//chain里面包含了request和response,按需获取
Request request = chain.request();
Response response = chain.proceed(request);
LogUtils.d(String.format("发送请求 %s",request.url()));
ResponseBody responseBody = response.peekBody(byteCount);
LogUtils.d(String.format("接收响应 %s", responseBody.string()));
return response;
}
}
- 网络拦截器进行网络缓存:
public class NetCacheInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
int onlineCacheTime = 60;
return response.newBuilder()
.header("Cache-Control", "public, max-age="+onlineCacheTime)
.removeHeader("Pragma")
.build();
}
}
4.自定义请求数据回调和过滤:
封装泛型实体类的观察者,统一处理结果。请求成功给下一层返回实体类。请求失败从HttpException中获取code设置对应的errorMsg
public abstract class ApiCallBack<M extends BaseModel> extends Subscriber<M> {
@Override
public void onCompleted() { }
@Override
public void onError(Throwable e) {
e.printStackTrace();
if (e instanceof HttpException) {
HttpException httpException = (HttpException) e;
int code = httpException.code();
//Http状态码提示
if (code >=400 && code< 500) {
LogUtils.e("请求错误");
} else if (code >= 500) {
LogUtils.e("服务器错误");
}
}
}
@Override
public void onNext(M baseModel) {
handleStatusCode(baseModel);
}
/**
* 后台statuscode状态码处理,状态码类型封装在StatusCodeEnum中
* @param baseModel
*/
private void handleStatusCode(M baseModel) {
String statusCode = baseModel.code;
StatusCodeEnum statusCodeEnum = StatusCodeEnum.getByCode(statusCode);
switch (statusCodeEnum) {
case RESULT_OK: //请求成功
onSuccess(baseModel);
break;
case RESULT_TOKENINVALID: //token失效
// TODO: 2018/11/23 token失效,删除本地用户信息储存并退出登录
break;
default:
LogUtils.e("请求失败错误");
break;
}
}
/**
* onSuccess回调的数据为程序具体需要的业务状态码,具体数据等
*/
public abstract void onSuccess(M m);
}
MVP加入:
1.View
Iview类:规定所有Activity,fragment等容器的公共行为,例如显示加载框和隐藏
public interface IView {
void showLoading();
void hideLoading();
}
IBaseView:
public interface IBaseView<M extends BaseModel> extends IView {
}
2.presenter
Ipresenter:
public interface Ipresenter<V extends IView> {
/**
* 关联P与V
* @param v
*/
void attachView(V v);
/**
* 取消关联P与V
*/
void detachView();
/**
* Rx订阅
*/
void subscribe(Observable observable, Subscriber subscriber);
/**
* Rx取消订阅
*/
void unSubscribe();
}
BasePresenter:
Basepresenter,抽象的persenter业务处理层。关联抽象层view和抽象model,通过CompositeSubscription关联数据请求,并通过subscriber回调回view层。
public class BasePresenter<V extends IBaseView> implements Ipresenter<V> {
protected V view;
protected ApiService apiService;
protected CompositeSubscription mCompositeSubscription;
@Override
public void attachView(IBaseView v) {
this.view = (V) v;
apiService = ApiManager.getApiService();
}
@Override
public void detachView() {
this.view = null;
unSubscribe();
}
@Override
public void subscribe(Observable observable, Subscriber subscriber) {
if (mCompositeSubscription == null) {
mCompositeSubscription = new CompositeSubscription();
}
//绑定observable与subscriber
Subscription subscription = observable.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(subscriber);
mCompositeSubscription.add(subscription);
}
@Override
public void unSubscribe() {
if (mCompositeSubscription != null && mCompositeSubscription.hasSubscriptions()) {
mCompositeSubscription.unsubscribe();
}
}
}
3.Model
BaseModel:请求数据实体类基类,对需要的data数据进行泛型处理
public class BaseModel<T> implements IModel,Serializable {
/** 自定义错误码 */
public String code;
/** 自定义业务状态码 */
public String bizcode;
/** 消息提示 */
public String msg;
/** 泛型实体类 */
public T data;
public boolean isOk() {
return bizcode.equals(AppConfig.BIZCODE_OK);
}
}
4.MvpActivity基类:
MvpActivity绑定presenter,在销毁时解绑,调用onUnsubscribe()将rxjava统一取消注册,以避免内存泄露。至于BaseActivity功能根据项目业务需求进行封装。比如跳转,加载弹出框,是否全屏,频繁调用工具类等。
public abstract class BaseMvpActivity<P extends BasePresenter> extends AppCompatActivity {
protected P mPresenter;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
mPresenter = createPresenter();
super.onCreate(savedInstanceState);
}
protected abstract P createPresenter();
@Override
protected void onDestroy() {
super.onDestroy();
//页面销毁时取消presenter绑定
if (mPresenter != null) {
mPresenter.detachView();
}
}
}
实现MainActivity的功能:
1.MainView:
public interface MainView extends IBaseView {
void getVideoData(BaseModel<VideoBean> videoBeanBaseModel);
}
2.MainPresenter:
public class MainPresenter extends BasePresenter<MainView> {
public MainPresenter(MainView mainView) {
attachView(mainView);
}
public void getVideoData() {
view.showLoading();
subscribe(apiService.getVideoData(), new ApiCallBack<BaseModel<VideoBean>>() {
@Override
public void onSuccess(BaseModel<VideoBean> videoBeanBaseModel) {
view.hideLoading();
view.getVideoData(videoBeanBaseModel);
}
});
}
}
2.MainActivity:
public class MainActivity extends BaseMvpActivity<MainPresenter> implements MainView{
private TextView tvContent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvContent = findViewById(R.id.tv_content);
mPresenter.getVideoData();
}
@Override
protected MainPresenter createPresenter() {
return new MainPresenter(this);
}
@Override
public void showLoading() {
}
@Override
public void hideLoading() {
}
@Override
public void getVideoData(BaseModel<VideoBean> videoBeanBaseModel) {
tvContent.setText(videoBeanBaseModel.data.toString());
}
}
好的,打完收工。