首页 > 学院 > 开发设计 > 正文

MVP理解与实践

2019-11-09 14:57:30
字体:
来源:转载
供稿:网友

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个测试目录:

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

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();}/** * 业务处理基类 */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(); } @Override public boolean onActivityResult(int requestCode, int resultCode, Intent data) { return false; } @Override public String[] registerLocalReceivers() { return new String[0]; } @Override public void onLocalReceive(Intent intent) { } @Override @CallSuper public void onDestroyView() { mActivity = null; mContext = null; mLoaderManager = null; }}

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


实现某个具体业务流程如下:

定义某个业务Presenter接口IXxPresenter extends IPresenter定义某个业务显示View接口IXxView extends IView实现某个业务Presenter–XxPresenter(增删查改) extends AbsPresenter implements IXxPresenter, LoaderManager.LoaderCallbacks<Cursor>private IXxView mView;private XxTask mXxTask;public XxPresenter(@NonNull IXxView view) { super(view); mView = view;}@Overridepublic Loader<Cursor> onCreateLoader(int id, Bundle args) {//返回一个new CursorLoader对象}@Overridepublic void onLoadFinished(Loader<Cursor> loader, Cursor data) {//完成对UI主界面的更新 if(mView != null) { mView.showXx(); }}@Overridepublic void onLoaderReset(Loader<Cursor> loader) {}@Overridepublic void queryXx() { mLoaderManager.destroyLoader(AppConst.LOADER_ID.XXX); mLoaderManager.initLoader(AppConst.LOADER_ID.XXX, null, this);}@Overridepublic void updateXx() { if (mXxTask == null || mXxTask.getStatus() != AsyncTask.Status.RUNNING) { mXxTask = new XxTask(); mXx.execute(); }}//deleteXx //saveXx(insert && update,根据是否有有效ID值判断)private void destroyLoader() { mLoaderManager.destroyLoader(AppConst.LOADER_ID.XXX); mLoaderManager.destroyLoader(AppConst.LOADER_ID.YYY);}@Overridepublic void onDestroyView() { destroyLoader(); if (mXxTask != null) { mXxTask.cancel(true); mXxTask = null; } mView = null; super.onDestroyView();}private class XxTask extends AsyncTask<Void, Void, Boolean> { 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实例化

/** * Presenter工厂,用于实例化相对的Presenter */public interface IPresenterFactory { /** * 返回Presenter实现类的实例 */ @Nullable IPresenter newPresenter(IView view, Class clazz);}/** * Presenter实例化工厂 */public class PresenterFactory implements IPresenterFactory { @Nullable @Override public 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); } }}/** * app application */public class XxApplication extends ApplicationWrapper { @Override public void onCreate() { super.onCreate(); ...... // presenter初始化 Presenter.init(new PresenterFactory()); ...... }}

Presenter与Activity绑定,Activity实现View接口

/** * 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<IPresenter> mPresenterList = new ArrayList<>(); private BroadcastReceiver mReceiver; @Override @CallSuper protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { AppBarActivity.this.onLocalReceive(intent); } }; registerLocalReceiver(); } @Override @CallSuper protected void onDestroy() { unregisterLocalReceiver(); for (IPresenter presenter : mPresenterList) { presenter.onDestroyView(); } super.onDestroy(); } /** * 查找控件 */ @CallSuper protected 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() { } @CallSuper public void addPresenter(IPresenter presenter) { mPresenterList.add(presenter); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == android.R.id.home) { onBackPressed(); return true; } else { return super.onOptionsItemSelected(item); } } @CallSuper protected void onLocalReceive(Intent intent) { for (IPresenter presenter : mPresenterList) { presenter.onLocalReceive(intent); } } @CallSuper protected String[] registerLocalReceivers() { ArrayList<String> allActionList = new ArrayList<>(); List<String> 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); }}XxActivity 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界面}
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表