Android MVP设计模式搭建(仿谷歌)

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了。

路还很长,慢慢走

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值