MVP模式概念

在MVP模式里通常包含4个要素:

  • View:负责绘制UI元素、与用户进行交互(在Android中体现为Activity);
  • View interface:需要View实现的接口,View通过View interface与Presenter进行交互,降低耦合,方便进行单元测试;
  • Model:负责存储、检索、操纵数据(有时也实现一个Model interface用来降低耦合);
  • Presenter:作为View与Model交互的中间纽带,处理与用户交互的负责逻辑。

  在Android开发中,Activity并不是一个标准的MVC模式中的Controller,它的首要职责是加载应用的布局和初始化用户界面,并接受并处理来自用户的操作请求,进而作出响应。随着界面及其逻辑的复杂度不断提升,Activity类的职责不断增加,以致变得庞大臃肿。
  当我们将其中复杂的逻辑处理移至另外的一个类(Presneter)中时,Activity其实就是MVP模式中 View,它负责UI元素的初始化,建立UI元素与Presenter的关联(Listener之类),同时自己也会处理一些简单的逻辑(复杂的逻辑交由 Presenter处理)。

MVP与MVC模式对比

MVP模式:

  • View不直接与Model交互,而是通过与Presenter交互来与Model间接交互
  • Presenter与View的交互是通过接口来进行的,更有利于添加单元测试
  • 通常View与Presenter是一对一的,但复杂的View可能绑定多个Presenter来处理逻辑

MVC模式:

  • View可以与Model直接交互
  • Controller是基于行为的,并且可以被多个View共享

MVP项目代码组织方式

项目含一个app src目录,4个测试目录:

  1. 测试目录
    分别是androidTest(UI层测试)、androidTestMock(UI层测试mock数据支持)、test(业务层单元测试)、mock(业务层单元测试mock数据支持)。

  2. src目录

  • 按照功能组织,功能内部分为xactivity、xcontract、xfragment、xpresenter四个类文件(x代表业务名称);
  • 按照类型组织,比如按照activity、adapter、fragment、contract、presenter进行划分,不同的类文件分别放到不同的目录中。

MVP具体应用实现

/** * mvp 中的 v */public interface IView {    /**     * 添加 presenter     */    void addPresenter(IPresenter presenter);    /**     * 结束当前view     */    void finish();}

/** * mvp中的P */public interface IPresenter {    /**     * 回调   * @return true,已经处理.     */    boolean onActivityResult(int requestCode, int resultCode, Intent data);    /**     * 注册广播   */    String[] registerLocalReceivers();    /**     * 接收到广播   */    void onLocalReceive(Intent intent);    /**     * UI销毁,释放view     */    void onDestroyView();}
```java /** * 业务处理基类 */ public abstract class AbsPresenter implements IPresenter {
protected AppCompatActivity mActivity;protected Context mContext;protected LoaderManager mLoaderManager;public AbsPresenter(@NonNull IView view) {    if (view instanceof AppCompatActivity) {        initWithActivity((AppCompatActivity) view);    } else if (view instanceof Fragment) {        initWithFragment((Fragment) view);    } else if (view instanceof ActivityInstrumentationTestCase2) {        ActivityInstrumentationTestCase2 testCase = (ActivityInstrumentationTestCase2) view;        mContext = testCase.getActivity();        mActivity = (AppCompatActivity) testCase.getActivity();        mLoaderManager = mActivity.getSupportLoaderManager();    } else {        throw new RuntimeException("view must be instance of AppCompatActivity or Fragment.");    }}private void initWithActivity(AppCompatActivity activity) {    mActivity = activity;    mContext = mActivity;    mLoaderManager = mActivity.getSupportLoaderManager();}private void initWithFragment(Fragment fragment) {    mActivity = (AppCompatActivity) fragment.getActivity();    mContext = fragment.getContext();    mLoaderManager = fragment.getLoaderManager();}@Overridepublic boolean onActivityResult(int requestCode, int resultCode, Intent data) {    return false;}@Overridepublic String[] registerLocalReceivers() {    return new String[0];}@Overridepublic void onLocalReceive(Intent intent) {}@Override@CallSuperpublic void onDestroyView() {    mActivity = null;    mContext = null;    mLoaderManager = null;}

}



------MVP中的M也就是Model层一般和Bean实体会抽离出来,作为中间件接口调用,如ModelService Module------

实现某个具体业务流程如下:1. 定义某个业务Presenter接口IXxPresenter extends IPresenter2. 定义某个业务显示View接口IXxView extends IView3. 实现某个业务Presenter--XxPresenter(增删查改) ```javapublic class XxPresenter extends AbsPresenter implements IXxPresenter, LoaderManager.LoaderCallbacks { private IXxView mView; private XxTask mXxTask; public XxPresenter(@NonNull IXxView view) { super(view); mView = view; } @Override public Loader onCreateLoader(int id, Bundle args) { //返回一个new CursorLoader对象 } @Override public void onLoadFinished(Loader loader, Cursor data) { //完成对UI主界面的更新 if (mView != null) { mView.showXx(); } } @Override public void onLoaderReset(Loader loader) { } @Override public void queryXx() { mLoaderManager.destroyLoader(AppConst.LOADER_ID.XXX); mLoaderManager.initLoader(AppConst.LOADER_ID.XXX, null, this); } @Override public void updateXx() { if (mXxTask == null || mXxTask.getStatus() != AsyncTask.Status.RUNNING) { mXxTask = new XxTask(); mXxTask.execute(); } } //deleteXx //saveXx(insert && update,根据是否有有效ID值判断) private void destroyLoader() { mLoaderManager.destroyLoader(AppConst.LOADER_ID.XXX); mLoaderManager.destroyLoader(AppConst.LOADER_ID.YYY); } @Override public void onDestroyView() { destroyLoader(); if (mXxTask != null) { mXxTask.cancel(true); mXxTask = null; } mView = null; super.onDestroyView(); } private class XxTask extends AsyncTask { private xx; private xxx; XxTask() { //初始化成员变量 } @Override protected Boolean doInBackground(Void... params) { //返回类型自定义 } @Override protected void onPostExecute(Boolean res) { super.onPostExecute(res); if (mView != null) { mView.showXx(); } } }}
Presenter工具类 ```java /** * 用于绑定presenter */ public class Presenter { // 负责生成Presenter的工厂类 private static IPresenterFactory sPresenterFactory;
private Presenter() {    // do nothing}/** * 初始化此Presenter类 */public static void init(@NonNull IPresenterFactory factory) {    sPresenterFactory = factory;}/** * view与presenter进行绑定 * @param view 当前进行绑定的view */public static void bind(@NonNull IView view, Class ...clazzs) {    if (sPresenterFactory == null) {        throw new RuntimeException("must invoke Presenter.init() to init IPresenterFactory first!");    }    for (Class clazz : clazzs) {        IPresenter presenter = sPresenterFactory.newPresenter(view, clazz);        if (presenter != null) {            view.addPresenter(presenter);        }    }}

}



Presenter实例化
```java/** * Presenter工厂,用于实例化相应的Presenter */public interface IPresenterFactory { /** * 返回Presenter实现类的实例 */ @Nullable IPresenter newPresenter(IView view, Class clazz);}
```java /** * Presenter实例化工厂 */ public class PresenterFactory implements IPresenterFactory {
@Nullable@Overridepublic IPresenter newPresenter(IView view, Class clazz) {    final String className = clazz.getName();    IPresenter presenter = null;        if (view instanceof IXxView && className.equals(IXxPresenter.class.getName())) {        IXxView xxView = (IXxView) view;        return new XxPresenter(xxView);    }  }

}




```java/** * app application */public class XxApplication extends ApplicationWrapper { @Override public void onCreate() { super.onCreate(); ...... // presenter初始化 Presenter.init(new PresenterFactory()); ...... }}
Presenter与Activity绑定,Activity实现View接口 ```java /** * Activity基类 */ public abstract class BaseActivity extends AppCompatActivity {
protected Context mContext = this;protected ActionBar mActionBar;protected Toolbar mToolbar;protected TextView mTitleTv;protected ImageView mIconIv;private List mPresenterList = new ArrayList<>();private BroadcastReceiver mReceiver;@Override@CallSuperprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    mReceiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            AppBarActivity.this.onLocalReceive(intent);        }    };    registerLocalReceiver();}@Override@CallSuperprotected void onDestroy() {    unregisterLocalReceiver();    for (IPresenter presenter : mPresenterList) {        presenter.onDestroyView();    }    super.onDestroy();}/** * 查找控件 */@CallSuperprotected void findWidget() {    mToolbar = (Toolbar) findViewById(R.id.toolbar);    mTitleTv = (TextView) findViewById(R.id.title_tv);    mIconIv = (ImageView) findViewById(R.id.logo_iv);}/** * 显示或隐藏标题图标,由子类去实现 */protected void showIcon(boolean show) {    if (show) {        mIconIv.setVisibility(View.VISIBLE);        mTitleTv.setVisibility(View.GONE);    } else {        mIconIv.setVisibility(View.GONE);        mTitleTv.setVisibility(View.VISIBLE);    }}/** * 设置标题 */public void setTitle(String title) {    mTitleTv.setText(title);}/** * 设置actionBar的显示和隐藏 */public void setActionBarVisibility(int visibility) {    mToolbar.setVisibility(visibility);}/** * 隐藏标题 */public void hideAppBar() {    if (mToolbar != null) {        mToolbar.setVisibility(View.GONE);    }}/** * 初始化控件 */protected void initWidget() {    if (mToolbar != null) {        setSupportActionBar(mToolbar);        mActionBar = getSupportActionBar();        if (mActionBar != null) {            mActionBar.setDisplayShowTitleEnabled(false);            mActionBar.setDisplayHomeAsUpEnabled(true);            mActionBar.setHomeAsUpIndicator(R.drawable.icon_back);        }    }}protected void setListener() {}@CallSuperpublic void addPresenter(IPresenter presenter) {    mPresenterList.add(presenter);}@Overridepublic boolean onOptionsItemSelected(MenuItem item) {    if (item.getItemId() == android.R.id.home) {        onBackPressed();        return true;    } else {        return super.onOptionsItemSelected(item);    }}@CallSuperprotected void onLocalReceive(Intent intent) {    for (IPresenter presenter : mPresenterList) {        presenter.onLocalReceive(intent);    }}@CallSuperprotected String[] registerLocalReceivers() {    ArrayList allActionList = new ArrayList<>();    List actionList;    for (IPresenter presenter : mPresenterList) {        actionList = Arrays.asList(presenter.registerLocalReceivers());        allActionList.addAll(actionList);    }    String[] actions = new String[allActionList.size()];    actions = allActionList.toArray(actions);    return actions;}private void registerLocalReceiver() {    LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(mContext);    IntentFilter intentFilter = new IntentFilter();    String[] actions = registerLocalReceivers();    for (String action : actions) {        intentFilter.addAction(action);    }    localBroadcastManager.registerReceiver(mReceiver, intentFilter);}private void unregisterLocalReceiver() {    LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(mContext);    localBroadcastManager.unregisterReceiver(mReceiver);}

}




```javaXxActivity extends BaseActivity implements IXxView, IXxxView, ...private IXxPresenter mXxPresenter;@Overrideprotected void onCreate(Bundle savedInstanceState) { Presenter.bind(this, IXxPresenter.class, IXxxPresenter.class, ...); super.onCreate(savedInstanceState); //setContentView() findWidget(); initWidget(); setListener();}@Overridepublic void addPresenter(IPresenter presenter) { super.addPresenter(presenter); if (presenter instanceof IXxPresenter) { mXxPresenter = (IXxPresenter) presenter; }...}/** * 初始化控件 */@Overrideprotected void initWidget() { super.initWidget(); if(mXxPresenter != null) { mXxPresenter.queryXx();//查询数据 }}@Overridepublic void showXx(params) {//传递数据//显示数据到UI界面}

更多相关文章

  1. 个人对于MVP的理解
  2. Android(安卓)之Context
  3. 关于android中activity的四种启动模式
  4. Android系统板子上电启动流程
  5. android使程序进程不被LMK杀死| application运行环境初始化
  6. IPC多进程模式学习笔记
  7. android+kotlin开发笔记(一)
  8. 结合Android浅谈Builder模式
  9. Andorid入门学习笔记整理(一)

随机推荐

  1. Android的手机震动
  2. android 9.0默认launcher
  3. Android Tutorial: Optimizing for Phone
  4. android 触摸手指动作放大和缩小图片
  5. Android联系人数据库全
  6. Android知识点剖析系列:深入了解layout_we
  7. Android画图Path的使用
  8. Android quota
  9. Android实现文件上传功能
  10. Android textView字间距自定义LetterSpac