Android MVP设计模式搭建(仿谷歌)
目前在使用的MVP模式,看了Android的模块化开发,发现此模式的迁移版,目前还没抽出时间后面会做一做模块化开发的Base版本
- 模块示意图
- 网络的封装
- 使用用例
- 总结
MVP模式示意图
以上的使用Presenter和Model用BaseActivity的范型
网络的封装
网络使用的是Retrofit+okhttp+Rxjava,使用方法见我的另一篇博客
新的项目中使用的是RxJava2,使用了被压封装的数据格式,简单的两个base代码提供在这
/**
* Created by ZhangHs on 2018/3/9.
*/
public abstract class BaseObserver<T> extends DisposableSubscriber<BaseBean<T>> {
private Context mContext;
private ProgressDialog progressDialog;
private Subscription subscription;
//默认无效果的请求
protected BaseObserver(Context context){
this.mContext=context.getApplicationContext();
}
//带进度条的请求
protected BaseObserver(Context context,boolean showProgress){
this.mContext=context.getApplicationContext();
if(showProgress){
progressDialog=new ProgressDialog(context);
progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialogInterface) {
subscription.cancel();
}
});
}
}
/*
@Override
public void onSubscribe(Subscription s) {
subscription=s;
Log.e("test","onSubscribe");
}
*/
@Override
public void onNext(BaseBean<T> value) {
//这里对数据bean的封装
Log.e("test","onNext done");
if(value!=null){
onHandleSuccess(value.getResult());
}
}
@Override
public void onError(Throwable e) {
if(progressDialog!=null){
progressDialog.dismiss();
}
Log.e("test","onError"+e.getMessage());
}
@Override
public void onComplete() {
if(progressDialog!=null&&progressDialog.isShowing()){
progressDialog.dismiss();
}
Log.e("test","onComplete");
}
protected abstract void onHandleSuccess(T t);
protected void onHandleError(String msg) {
Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show();
}
}
这里是RxSchedulers,提供不同的compose
/**
* Created by ZhangHs on 2018/3/9.
* * 设置同一的拦截,对每个订阅做相同的标准,这个比另一个要好,可以添加自己想要的compose
*/
public class RxSchedulers {
public static <T> ObservableTransformer<T, T> compose() {
return new ObservableTransformer<T, T>() {
@Override
public ObservableSource<T> apply(Observable<T> observable) {
return observable
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.doOnSubscribe(new Consumer<Disposable>() {
@Override
public void accept(Disposable disposable) throws Exception {
// if(!NetWorkUtils.isNetConnected(context)){
// Toast.
makeText(context,"网络异常",Toast.LENGTH_SHORT).show();
// }
}
})
.observeOn(AndroidSchedulers.mainThread());
}
};
}
public static <T> FlowableTransformer<T, T> io_main() {
return new FlowableTransformer<T, T>() {
@Override
public Publisher<T> apply(Flowable<T> upstream) {
return upstream.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
};
}
}
使用用例
你的项目里使用的是BaseActivity的封装方式的话,那可以很简单的封装进来,如下
BasePresenter
/**
* @author ZhangHs
* @date 2017/11/17
* @description
* @version
*/
public abstract class BasePresenter<T,E> {
public Context mContext;
public E mModel;
public T mView;
public void setVM(T view, E model) {
this.mView = view;
this.mModel = model;
}
public void onDestroy(){
}
}
BaseModel以及BaseView 看你的业务需求,我写的是空的接口
然后哪个Activity需要使用,写一个Contact
/**
* Created by ZhangHs on 2018/4/12.
*/
public interface MainContact {
interface Model extends BaseModel{
Flowable<BaseBean<ResultBean>> queryMovie(String q, String key);
}
interface View extends BaseView {
void requestResbonse(ResultBean resultBean);
}
abstract class Presenter extends BasePresenter<View,Model> {
public abstract void requestQueryVideo(String q,String key) ;
}
}
对具体的Presenter以及Model实现
/**
* Created by ZhangHs on 2018/4/12.
*/
public class MainPresenter extends MainContact.Presenter{
@Override
public void requestQueryVideo(String q, String key) {
mModel.queryMovie(q,key).subscribe(new BaseObserver<ResultBean>(mContext){
@Override
protected void onHandleSuccess(ResultBean resultBean) {
Log.e("test","onHandleSuccess");
if(resultBean!=null){
mView.requestResbonse(resultBean);
}
}
});
}
}
public class MainModel implements MainContact.Model {
@Override
public Flowable<BaseBean<ResultBean>> queryMovie(String q, String key) {
return ApiAwaken.getInstance(ApiInterface.class).getVideo(q,key)
.compose(RxSchedulers.<BaseBean<ResultBean>>io_main());
}
}
BaseActivity使用
/**
* Created by ZhangHs on 2018/4/12.
* 业务逻辑层的base 不涉及view
*/
public abstract class BaseActivity
<T extends BasePresenter,E extends BaseModel> extends AppCompatActivity{
mPresenter = TUtil.getT(this, 0);
mModel= TUtil.getT(this,1);
if(mPresenter!=null){
mPresenter.mContext=this;
}
//这里的presenter关联的方法可以交给子类,方便简单的Activity不需要Presenter的情况
this.initPresenter();
/**
* 实现presentor 与model的关联
*/
public abstract void initPresenter();
}
获取范型的实例的方法
/**
* ZhangHs
* 类转换初始化
*/
public class TUtil {
public static <T> T getT(Object o, int i) {
try {
return ((Class<T>) ((ParameterizedType) (o.getClass()
.getGenericSuperclass())).getActualTypeArguments()[i])
.newInstance();
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
} catch (ClassCastException e) {
}
return null;
}
public static Class<?> forName(String className) {
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
}
具体Activity的使用
public class MainActivity22 extends BaseViewActivity<MainPresenter,MainModel>
implements MainContact.View{
@Override
public void initPresenter() {
mPresenter.setVM(this,mModel);
}
@Override
public void initView() {
//请求网络
mPresenter.requestQueryVideo("三国","345d9ef5980ee4e851644a457a56dbb2");
}
@Override
public void requestResbonse(ResultBean resultBean) {
//View接口层的回掉
tv_show.setText(resultBean.getDesc());
}
}
总结
当然对生命周期的处理,这里并没有处理,你可以自己看业务相应添加,还有Presenter的使用和Model也可以用annotation注入的方式,可以直接写在每个activity上,看你操作了,代码很简单,设计思路比较清晰,后面的填坑者占领你的坑位时就不会mmp了。
路还很长,慢慢走