Android Mvp+DataBinding架构模式详解

来源:互联网 发布:c语言获取网页内容 编辑:程序博客网 时间:2024/05/22 08:26

MVP模式的使用

一. MVC与MVP设计模式的区别

  1. MVC:用户发出事件的时候,view层发出指令到controller层,controller层去通知model层更新数据,更新完数据后返回给view层展示。

    MVC反映到Android工程上

    • V:layout.xml布局文件就相应于MVC的View层
    • M:各种javaBean,第三方库类,ApiService,一系列helper和manager
    • C:activity

    MVC的缺点:

    • layout作为view层,控制能力太弱。
    • 代码写在activity中,造成了activity即是controller层,又是view层的现象
    • view层和model层相互可知,两者之间存在耦合
  2. MVP:
    对于Android来说,MVP的model层为数据处理层;View为试图,比如activity和fragment;Presenter为业务逻辑处理层和中间层,主持人的角色,处理流程控制。

    相比于MVC,MVP中的view层和model层不再相互可知,完全的解耦 。使用presenter充当桥梁的作用,

用于操作view层发出的事件传到presenter层中,presenter层通知model层进行数据处理,并且将处理完成的数据返回给 view层显示。

  另外view层和presenter层也是解耦开来,两者之间的通信可以通过接口实现,在activity或者fragment实现view层定义好的接口,在presenter中通过接口调用方法  最好的方式是使用fragment作为view层,而activty则用于创建view层和presenter层的一个控制器。

二. MVP模式详细解析

  使用MVP,至少经历以下几个步骤:(M不能调用P层)
  • 创建IPresenter接口,定义好所有的业务逻辑接口,并且创建它的实现类PresenterCompl。
  • 创建IView接口,定义好所有试图逻辑的接口,实现类就是当前的Activity和Fragment
  • Activity 里包含了一个 IPresenter,而 PresenterCompl 里又包含了一个 IView 并且依赖了 Model。Activity 里只保留对 IPresenter 的调用,其它工作全部留到 PresenterCompl 中实现。
  • Model :不是传统意义上的Model,而是一个ModelManager数据处理中心,可以处理网络数据,数据库,文件以及关于Android中的四大组件的交互包含BroadcastReceiver,Service中的,都可以集中在这里面处理。
    某一个模块的网络处理可以写一个NetWorkModel,数据库操作写一个DbModel(或者只写一个RepositoryModel同时处理网络和数据库的数据,建议三个Model都写),同时继承BaseMode。Model层并不是必须有的,但是一定会有 View 和 Presenter。(也可以在P层处理简单的数据,怎么方便怎么来,不拘于模式)
  • ViewMode:使用RecyclerView的Adapter,采用ViewModel+IView的方式,IView的setData方法中处理数据绑定

    MVP的实践:

  1. Base层BasePresenter      public abstract class BasePresenter<V> {          private Reference<V> mUIRef;          protected V mView;          void onAttach(V view) {              mUIRef = new WeakReference<V>(view);              mView = mUIRef.get();          }          void onDetach() {              if (mUIRef != null) {                  mUIRef.clear();                  mUIRef = null;              }          }          protected V getView() {              if (mUIRef == null) {                  return null;              }              return mUIRef.get();          }          public boolean isUIAttached() {              return mUIRef != null && mUIRef.get() != null;          }      }
  1. Base层BaseMVPActivity
   public abstract class BaseMVPActivity<V, P extends BasePresenter<V>> extends AppCompatActivity {        private P presenter;        @Override        protected void onCreate(@Nullable Bundle savedInstanceState) {            super.onCreate(savedInstanceState);            setContentView(getLayoutId());            presenter = createPresenter();            presenter.onAttach((V) this);            initView();            initListener();        }        @Override        protected void onDestroy() {            super.onDestroy();            presenter.onDetach();        }        public abstract P createPresenter();        public P getPresenter() {            return presenter;        }        public abstract int getLayoutId();        public abstract void initView();        public abstract void initListener();    }
  1. Base层Model:
     /**        * 可用于数据操作,网络,数据库,和文件等等        * NetWorkModel 网络操作        * DatabaseModel 数据库操作        * RepositoryModel(同时调NetWorkModel和DatabaseModel) 同时操作网络和数据库        * 以上看情况选择        * @author : liujian        * @since : 2017/9/3        */       public interface BaseModel<D> {           interface LoadTaskCallBack<D> {               void onTasksLoaded(List<D> list);               void onLoadFailed();           }           interface UpdateTaskCallBack {               void onUpdateSucceed();               void onUpdateFailed();           }           void getData(LoadTaskCallBack callBack);           void saveData(D d, UpdateTaskCallBack callBack);           void updateData(D d, UpdateTaskCallBack callBack);           void deleteData(String id, UpdateTaskCallBack callBack);           void deleteAllData(UpdateTaskCallBack callBack);       }
  1. View层接口ILoginView:
    public interface ILoginView {        void clearTextView();        void onLoginResult(boolean result);        void showEmptyInfo();    }
  1. Presenter层接口ILoginPresenter
      public abstract class ILoginPresenter extends BasePresenter<ILoginView>{           public abstract void clear();           public abstract void login(String name, String password);       }
  1. Model层接口ILoginModel
   public interface ILoginModel {        public interface OnLoginCallBack {            void onLoginSuccess();            void onLoginFailed();        }        void login(String name, String password, OnLoginCallBack callBack);    }
  1. View层实现类LoginActivity
    public class LoginActivity extends BaseMVPActivity<ILoginView, ILoginPresenter> implements ILoginView, View.OnClickListener {        private AppCompatEditText nameET;        private AppCompatEditText passwordET;        @Override        public int getLayoutId() {            return R.layout.activity_login;        }        @Override        public ILoginPresenter createPresenter() {            return new LoginPresenterImpl();        }        @Override        public void showEmptyInfo() {            Toast.makeText(this, "name or password is empty", Toast.LENGTH_LONG).show();        }        @Override        public void initView() {            nameET = (AppCompatEditText) findViewById(R.id.et_name);            passwordET = (AppCompatEditText) findViewById(R.id.et_password);        }        @Override        public void initListener() {            findViewById(R.id.btn_login).setOnClickListener(this);            findViewById(R.id.btn_clear).setOnClickListener(this);        }        @Override        public void clearTextView() {            nameET.setText("");            passwordET.setText("");        }        @Override        public void onLoginResult(boolean result) {            if (result) {                Intent intent = new Intent(this, MainActivity.class);                startActivity(intent);            } else {                Toast.makeText(this, "Login false", Toast.LENGTH_SHORT).show();            }        }        @Override        public void onClick(View view) {            String name = nameET.getText().toString();            String password = passwordET.getText().toString();            switch (view.getId()) {                case R.id.btn_clear:                    getPresenter().clear();                    break;                case R.id.btn_login:                    getPresenter().login(name, password);                    break;            }        }    }1. Presenter实现类LoginPresenterImpl    public class LoginPresenterImpl extends ILoginPresenter implements ILoginModel.OnLoginCallBack {        private ILoginModel loginModel;        public LoginPresenterImpl() {            loginModel = new LoginModelImpl(this);        }        @Override        public void clear() {            view.clearTextView();        }        @Override        public void login(String name, String password) {            if (TextUtils.isEmpty(name) || TextUtils.isEmpty(password)) {                view.showEmptyInfo();            }            loginModel.login(name, password, this);        }        @Override        public void onLoginSuccess() {            view.onLoginResult(true);        }        @Override        public void onLoginFailed() {            view.onLoginResult(false);        }    }1. Model层LoginModelImpl    public class LoginModelImpl implements ILoginModel {        private ILoginPresenter presenter;        public LoginModelImpl(ILoginPresenter presenter) {            this.presenter = presenter;        }        @Override        public void login(String name, String password, OnLoginCallBack callBack) {            //模拟执行网络请求            if (name.equals("123") && password.equals("1234")) {                callBack.onLoginSuccess();            } else {                callBack.onLoginFailed();            }        }    }

三. MVP+data binding的开发模式

  1. MVP中数据绑定setText和setListener等操作通过DataBinding的方式来实现

  2. JavaBean继承BaseObservable类,给layout布局的data节点传入javaBean对象

  3. MVP+DataBinding与MVVM的区别:
    a. MVVM直接通过Databinding给Layout布局传入ViewModel对象,view层的事件处理和数据(JavaBean)获取直接在viewModel中处理
    b. MVP+DataBinding通过DataBinding给Layout布局传入ViewModel实体类,且该实体类对象是通过Presenter层获取传入到View层,View层的事件处理还是在View层处理
原创粉丝点击