浅谈MVC,MVP,MVVM三种架构模式

1.MVC架构模式

View:对应的xml布局文件
Model:实体模型(JavaBean)
Controllor:对应于Activity业务逻辑,数据处理和UI处理

该模式的特点,就是当某个界面非常复杂的时候,activity代码量会上千行的增加,非常冗余。

2.MVP架构模式

View:对应的xml布局文件
Model:实体模型(JavaBean)
Presenter:责完成View于Model间的交互和业务逻辑

搭建MVP的一个栗子

(1).创建一个持有View接口的基类的BasePersenter

public class BasePersenter implements Persenter {
    protected T mView;//View接口
    protected WebService mRetrofit = MyRertofit.getLoginService().create(WebService.class);
    protected CompositeSubscription mCompositeSubscription;

    public BasePersenter(T t) {
        attachView(t);
    }

    @Override
    public void attachView(T view) {
        this.mView = view;
    }

    @Override
    public void detachView() {
        this.mView = null;
        onUnsubscribe();
    }

    public void onUnsubscribe() {
        if (mCompositeSubscription != null && mCompositeSubscription.hasSubscriptions()) {
            mCompositeSubscription.unsubscribe();
        }
    }

    /***
     * 通用的网络请求的方法
     * @param observable
     * @param subscriber
     */
    public void addSubscription(Observable observable, Subscriber subscriber) {
        if (mCompositeSubscription == null) {
            mCompositeSubscription = new CompositeSubscription();
        }
        if (!NetworkUtils.isConnected()) {
            ToastUtils.showShort("网络不可用,请检查网络~");
        }
        mCompositeSubscription.add(observable
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(subscriber));
    }
}

(2).新建一个继承BasePersenter的PayCarPersenter

public class PayCarPersenter extends BasePersenter{
    public PayCarPersenter(PayCarView baseResultBaseView) {
        super(baseResultBaseView);
    }

    public void  getDetail(String rechargeAmount,String giftAmount){
        mView.OnGetPayInfoLoading();
        HashMap map = new HashMap();
        map.put("userId",  SharedPreferencesUtils.getString(App.application, Constans.USER_ID, ""));
        map.put("rechargeAmount",rechargeAmount);
        map.put("giftAmount",giftAmount);
        map.put("terminal","1");
        addSubscription(mRetrofit.recharge(map),new SubscriberCallBack<>(new ApiCallback>() {
            @Override
            public void onSuccess(BaseResult payCarBeanBaseResult) {
                if (payCarBeanBaseResult.getSuccess()){
                    mView.OnGetPayInfoSuccess(payCarBeanBaseResult.getResultObject());
                }else{
                    mView.OnGetPayInfoError("获取充值信息失败,请重试~");
                }
            }

            @Override
            public void onFailure(int code, String msg) {
                mView.OnGetPayInfoError("获取充值信息失败,请重试~");
            }

            @Override
            public void onCompleted() {
                mView.OnGetPayInfoComplete();
            }
        }));
    }

    public void toPay(String orderId){
        mView.OnToPayLoading();
        HashMap map = new HashMap();
        map.put("orderNumber",  orderId);
        map.put("payType","11");
        map.put("ip", NetworkUtils.getIPAddress(true));
        map.put("orderType","recharge");
        map.put("payWay","4");
        map.put("isRaw","1");
        addSubscription(mRetrofit.getzxPlay(map),new SubscriberCallBack<>(new ApiCallback>() {
            @Override
            public void onSuccess(BaseResult stringBaseResult) {
                if (stringBaseResult.getSuccess()){
                    mView.OnToPaySuccess(stringBaseResult.getResultObject());
                }else{
                    mView.OnToPayError("获取支付信息失败,请重试~");
                }
            }

            @Override
            public void onFailure(int code, String msg) {
                mView.OnToPayError("获取支付信息失败,请重试~");
            }

            @Override
            public void onCompleted() {
                mView.OnToPayComplete();
            }
        }));
    }
}

(3).PayCarView 接口

public interface PayCarView {
void OnGetPayInfoSuccess(PayCarBean bean);

void OnGetPayInfoError(String msg);

void OnGetPayInfoComplete();

void OnGetPayInfoLoading();

void OnToPaySuccess(Object bean);

void OnToPayError(String msg);

void OnToPayComplete();

void OnToPayLoading();
}

(4).新建一个持有presenter基类MvpActivity或者MvpFragment

public abstract class MvpActivity

extends BaseActivity { protected P mPersenter; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { mPersenter = createPersenter(); super.onCreate(savedInstanceState); } protected abstract P createPersenter(); @Override protected void onDestroy() { super.onDestroy(); if (mPersenter != null) mPersenter.detachView(); } }

(5).新建一个继承自MvpActivity的子Activity,实现抽象方法createPersenter()

public class PayCarActivity extends MvpActivity implements PayCarView {
    @BindView(R.id.tv_zhensong)
    TextView tv_zhensong;
    @BindView(R.id.tv_shij)
    TextView tv_shij;
    @BindView(R.id.tv_money)
    TextView tv_money;
    @BindView(R.id.tv_order_id)
    TextView tv_order_id;
    private IWXAPI api;

    @Override
    protected PayCarPersenter createPersenter() {
        return new PayCarPersenter(this);
    }

    @Override
    protected void onError() {
        initData();
    }

    @Override
    protected void onBack() {
        showGiveUpPayDialog();
    }

    @Override
    protected int setRootView() {
        return R.layout.activity_pay_cart;
    }

    @Override
    protected void initData() {
        mPersenter.getDetail(getStringExtra("money"), getStringExtra("disMoney"));
    }

    /***
     * 放弃支付提示框
     */
    private void showGiveUpPayDialog() {
        DialogUtils.showDialog(this, "提示", "确定放弃充值?使用会员卡储值,\n立享更多优惠哦?", maAlertDialog -> {
            maAlertDialog.dismiss();
            finish();

        });
    }

    @Override
    protected void initToolBar() {
        setTitle("确认支付");
    }

    @Override
    protected void initView(Bundle savedInstanceState) {
        api = WXAPIFactory.createWXAPI(this, Constans.APP_ID);
    }

    @OnClick(R.id.ll_wx_pay)
    public void toPay() {
        if (api.isWXAppInstalled()) {
            //检测当前微信版本是否支持微信支付
            boolean isPaySupported = api.getWXAppSupportAPI() >= Build.PAY_SUPPORTED_SDK_INT;
            if (isPaySupported) {
                mPersenter.toPay(tv_order_id.getText().toString());
            } else {
                ToastUtils.showLong("您当前的微信版本过低,不支持微信支付");
            }
        } else {
            ToastUtils.showLong("您没有安装微信,请您安装后再支付");
        }

    }

    @Override
    public void OnGetPayInfoSuccess(PayCarBean bean) {
        tv_money.setText(bean.getRechargeAmount() + "");
        tv_order_id.setText(bean.getOrderId());
        tv_shij.setText(bean.getRealAmount() + "元");
        tv_zhensong.setText(bean.getGiftAmount() + "元");
        overLoading();
    }

    @Override
    public void OnGetPayInfoError(String msg) {
        showToast(msg);
        showError();
    }

    @Override
    public void OnGetPayInfoComplete() {

    }

    @Override
    public void OnGetPayInfoLoading() {
        toLoading();
    }

    @Override
    public void OnToPaySuccess(Object bean) {
        App.rechargeMoney = tv_money.getText().toString().trim();
        JSONObject jsonObject = null;
        JSONObject json = null;
        try {
            jsonObject = new JSONObject(bean.toString());
            json = jsonObject.optJSONObject("pay_info");
            PayReq req = new PayReq();
            req.appId = json.optString("appid");
            req.partnerId = json.optString("partnerid");
            req.prepayId = json.optString("prepayid");
            req.nonceStr = json.optString("noncestr");
            req.timeStamp = json.optString("timestamp");
            req.packageValue = json.optString("package");
            req.sign = json.optString("sign");
            req.extData = "app data";
            Constans.payFrom = 3;
            api.sendReq(req);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void OnToPayError(String msg) {
        showToast(msg);
    }

    @Override
    public void OnToPayComplete() {
        closeLoading();
    }

    @Override
    public void OnToPayLoading() {
        showLoadding("正在获取支付信息~");
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        // TODO Auto-generated method stub
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            showGiveUpPayDialog();
        }
        return false;
    }

    @Subscribe
    public void toWebWxPay(WebPayEvent webPayEvent) {
        switch (webPayEvent.getVar()) {
            case 0:
                startActivity(RechargeSuccessActivity.class);
                AppManager.getAppManager().finishActivity(StoreValueCardActivity.class);
                finish();
                break;
            default:
                DialogUtils.showNoCancleDialog(PayCarActivity.this, "支付说明", "用户支付失败或取消支付", maAlertDialog -> {
                    maAlertDialog.dismiss();
                });
                break;
        }

    }
}
核心就是Activity实现View的接口,并持有Presenter对象,Presenter中持有Model和View对象,负责完成View于Model间的交互和业务逻辑,本文中的Prsenter并没有Model,而是直接新建了一些类似model中的请求方法,这样可以省掉Model接口和ModelIml接口实现类,简化代码。

3.MVVM架构

View:对应的xml布局文件
Model:实体模型(JavaBean)
ViewModel:责完成View于Model间的交互和业务逻辑(依赖于Google的Databing框架)

MVVM的目标和思想MVP类似,利用数据绑定(Data Binding)、依赖属性(Dependency Property)等新特性,打造了一个更加灵活高效的架构。

(1)######DataBing框架的使用(https://www.jianshu.com/p/d429174b8d07)
ObservableField 以及它的派生 ObservableBoolean、 ObservableByte ObservableChar、ObservableShort、ObservableInt、ObservableLong、ObservableFloat、ObservableDouble、 ObservableParcelable 支持双向绑定,只要数据变了,xml文件中的数据会自动刷新。

image.png




    

        

        

        

        

        

    

    

        

        

        

        

        
public class DoubleBindBean2 {
    //变量需要为public
    public final ObservableField username = new ObservableField<>();
}
public class DoubleBindActivity extends AppCompatActivity implements View.OnClickListener {

    private DoubleBindBean2 doubleBindBean2;
    private boolean flag2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityDoubleBindBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_double_bind);

        doubleBindBean2 = new DoubleBindBean2();
        doubleBindBean2.username.set("我是原始内容2");
        binding.setDoubleBindBean2(doubleBindBean2);

        binding.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.change_content_btn2:
                //ObservableFields
                flag2 = !flag2;
                if (flag2) {
                    doubleBindBean2.username.set("我是更新后的内容2");
                } else {
                    doubleBindBean2.username.set("我是原始内容2");
                }
                break;
        }
    }
}

(2).基于DataBinding框架,搭建MVVM框架,和MVP类似
A:新建一个ViewModel的类似Presenter的类,持有bing对象,或着adapter对象,然后ViewModel中做网络请求,和然后通过bind.setBean()进行数据刷新即可,不需要回调到Activity中进行处理,直接在ViewModel中就完成了数据的更新。
B:Activity中持有ViewModel的对象,通过该对象,调用内部网络请求等各种方法。

你可能感兴趣的:(浅谈MVC,MVP,MVVM三种架构模式)