亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

MVP理解與實踐

2019-11-09 14:03:56
字體:
來源:轉載
供稿:網友

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界面}
上一篇:隱式Intent

下一篇:設計模式之策略模式

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美性生交大片免网| 亚洲精品国产精品国自产观看浪潮| 久久影视电视剧凤归四时歌| 在线国产精品播放| 国产精品美女免费视频| 国产精品福利网站| 亚洲最新视频在线| 中文字幕亚洲一区二区三区| 狠狠久久五月精品中文字幕| 亚洲国产精久久久久久久| 亚洲精品一二区| 亚洲成年人在线| 成人日韩av在线| 人人澡人人澡人人看欧美| 欧美在线一级视频| 亚洲永久免费观看| 国产女同一区二区| 欧美中文字幕视频在线观看| 欧美风情在线观看| 久久精品中文字幕免费mv| 亚洲а∨天堂久久精品喷水| 亚洲午夜精品久久久久久性色| 日韩欧美精品中文字幕| 日韩av在线资源| 国产精品国产三级国产专播精品人| 伊人久久大香线蕉av一区二区| 日本久久久a级免费| 亚洲欧美中文字幕| 丰满岳妇乱一区二区三区| 狠狠久久五月精品中文字幕| 九九热这里只有精品免费看| 日韩视频一区在线| 狠狠躁18三区二区一区| 视频在线观看一区二区| 日韩美女毛茸茸| 午夜剧场成人观在线视频免费观看| 国产精品自在线| 日韩在线观看精品| 国产精品盗摄久久久| 日韩在线观看免费全集电视剧网站| 亚洲第一区中文99精品| 精品久久久久久久久久久久| 亚洲人午夜精品| 日本不卡免费高清视频| 亚洲精品美女免费| 日韩美女在线观看一区| 日韩精品免费视频| 亚洲精品电影在线观看| 色偷偷888欧美精品久久久| 欧美激情中文字幕在线| 人妖精品videosex性欧美| 91wwwcom在线观看| 亚洲精品日韩激情在线电影| 日韩国产中文字幕| 色樱桃影院亚洲精品影院| 亚洲国产美女久久久久| 久久免费精品日本久久中文字幕| 91亚洲精品在线| 色婷婷综合久久久久中文字幕1| 国外视频精品毛片| 亚洲视频专区在线| 亚洲激情视频在线| 欧美一级片在线播放| 91精品啪在线观看麻豆免费| 奇米一区二区三区四区久久| 欧美美女操人视频| 久久久人成影片一区二区三区| 亚洲视频国产视频| 亚洲区在线播放| 国产精品香蕉av| 最近2019年好看中文字幕视频| 欧美在线性爱视频| 欧美性生交xxxxxdddd| 欧美日韩视频免费播放| 国内精品久久久久影院优| 欧美日韩一区二区在线播放| 深夜福利日韩在线看| 国产欧美精品一区二区三区介绍| 亚洲一区美女视频在线观看免费| 国产精品视频精品| 欧美色videos| 黑人巨大精品欧美一区二区三区| 一本色道久久综合亚洲精品小说| 欧美人与性动交| 成人免费网视频| 欧美黑人一级爽快片淫片高清| 亚洲国产小视频| 精品国产成人在线| 亚洲日本欧美日韩高观看| 操日韩av在线电影| 69av在线播放| 久久久精品国产网站| 欧美日韩在线一区| 91高清视频免费| 欧美激情一区二区三区成人| 91极品女神在线| 亚洲欧美国内爽妇网| 中文字幕国内精品| 欧美激情xxxx| 日韩av电影在线免费播放| 777午夜精品福利在线观看| 亚洲美女av网站| 永久免费毛片在线播放不卡| 日本高清久久天堂| 欧美电影免费观看| 欧美在线视频播放| 日韩在线播放视频| 欧美中文字幕视频| 亚洲高清一区二| 亚洲国产精品系列| 国产精品第二页| 国产精品视频久久久久| 欧美精品免费播放| 欧美激情一级精品国产| 久久久噜噜噜久久中文字免| 久久久久久久一| 精品国产一区二区三区久久| 久久精品视频中文字幕| 欧美猛男性生活免费| 亚洲无av在线中文字幕| 日韩高清av一区二区三区| 亚洲最大福利视频网| 夜夜嗨av一区二区三区免费区| 亚洲成人激情小说| 亚洲国产欧美一区二区三区同亚洲| 成人444kkkk在线观看| 色伦专区97中文字幕| 欧美性色xo影院| 欧美日韩一区二区精品| 国产在线精品自拍| 超在线视频97| 粗暴蹂躏中文一区二区三区| 5278欧美一区二区三区| 欧美影院成年免费版| 日韩国产高清污视频在线观看| 欧美体内谢she精2性欧美| 国产欧美精品久久久| 国产精品爽爽ⅴa在线观看| 欧美裸体视频网站| 欧美激情一级精品国产| 97激碰免费视频| 国产午夜一区二区| 亚洲欧美精品suv| 欧美性猛交丰臀xxxxx网站| 成人h片在线播放免费网站| 午夜精品视频网站| 超碰91人人草人人干| 日韩av最新在线| 毛片精品免费在线观看| 韩国一区二区电影| 久久人人爽人人爽人人片av高清| 亚洲视频电影图片偷拍一区| 国产精品国产三级国产aⅴ浪潮| 国产不卡av在线免费观看| 8050国产精品久久久久久| 九九热最新视频//这里只有精品| 欧美日韩在线另类| 欧美做爰性生交视频| 国产欧美精品在线| 日韩精品久久久久久久玫瑰园| 色妞色视频一区二区三区四区| 国产自产女人91一区在线观看| 亚洲精品日韩欧美| 欧美成人三级视频网站|