美文网首页
浅谈MVC,MVP,MVVM三种架构模式

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

作者: Owen270 | 来源:发表于2019-04-09 15:32 被阅读0次

    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<T> implements Persenter<T> {
        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<PayCarView>{
        public PayCarPersenter(PayCarView baseResultBaseView) {
            super(baseResultBaseView);
        }
    
        public void  getDetail(String rechargeAmount,String giftAmount){
            mView.OnGetPayInfoLoading();
            HashMap<String, String> 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<BaseResult<PayCarBean>>() {
                @Override
                public void onSuccess(BaseResult<PayCarBean> 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<String, String> 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<BaseResult<Object>>() {
                @Override
                public void onSuccess(BaseResult<Object> 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<P extends BasePersenter> 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<PayCarPersenter> 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
    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools">
    
        <data>
    
            <variable
                name="doubleBindBean"
                type="com.zx.databindingdemo.bean.DoubleBindBean" />
    
            <variable
                name="doubleBindBean2"
                type="com.zx.databindingdemo.bean.DoubleBindBean2" />
    
            <variable
                name="list"
                type="android.databinding.ObservableArrayList&lt;String&gt;" />
    
            <variable
                name="map"
                type="android.databinding.ObservableArrayMap&lt;String,Object&gt;" />
    
            <variable
                name="onClickListener"
                type="android.view.View.OnClickListener" />
    
        </data>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:padding="15dp">
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{doubleBindBean.content}" />
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{doubleBindBean2.username}" />
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@{list[0]}" />
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text='@{map["key0"]}' />
    
            <Button
                android:id="@+id/change_content_btn"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="@{onClickListener}"
                android:textAllCaps="false"
                android:text="BaseObservable方式改变内容" />
    
            <Button
                android:id="@+id/change_content_btn2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="@{onClickListener}"
                android:textAllCaps="false"
                android:text="ObservableFields方式改变内容" />
    
    
            <Button
                android:id="@+id/change_content_btn3"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="@{onClickListener}"
                android:textAllCaps="false"
                android:text="list改变内容" />
    
    
            <Button
                android:id="@+id/change_content_btn4"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:onClick="@{onClickListener}"
                android:textAllCaps="false"
                android:text="map改变内容" />
    
        </LinearLayout>
    </layout>
    
    
    public class DoubleBindBean2 {
        //变量需要为public
        public final ObservableField<String> 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三种架构模式

          本文链接:https://www.haomeiwen.com/subject/hrcelqtx.html