日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

MVP架构模式详解

發布時間:2024/5/24 综合教程 46 生活家
生活随笔 收集整理的這篇文章主要介紹了 MVP架构模式详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一.為什么需要軟件設計模式?

我們先來定義什么是好的軟件架構:

軟件架構上具有明確的分工,各個模塊的功能職責平衡分配,且明確。
可測試性,通常良好的軟件架構都具備良好的可測試性。
良好的易用性,維護成本低。

為什么需要模塊分工?

良好的模塊分工,可以大大簡化我們對代碼的理解難度。雖然通過大量的開發工作,可以訓練我們的大腦去分析越來越復雜的邏輯,但是人總有極限,而且簡單的邏輯更容易理解、不容易出錯,所以,遵循單一職責原則,將復雜的業務邏輯分解。

為什么需要良好的可測試性?

對于深知單元測試好處的開發者來說,這并不是一個問題。單元測試可以大大地減少程序運行時才能發現的問題,這通常可以節省「用戶反饋」->「Bug修復」->「新版本發布」->「用戶安裝新版本」這個耗時長達一周以上的過程。所以,程序的可測試性對于程序的穩定性是異常重要的。

為什么需要良好的易用性?

毋庸置疑,最好的代碼是還沒被寫出來的代碼。因此,越少的代碼,意味著越少的 bugs。這也意味著盡量以最少的代碼實現相同的功能,并非意味著這個開發者懶惰,同時,也不能不看維護成本而盲目贊同一個看似聰明的方案。


二.什么是MVP架構?

MVP是單詞Model View Presenter的首字母的縮寫,分別表示數據層、視圖層、發布層,它是MVC架構的一種演變。作為一種新的模式,MVP與MVC有著一個重大的區別:在MVP中View并不直接使用Model,它們之間的通信是通過Presenter (MVC中的Controller)來進行的,所有的交互都發生在Presenter內部,而在MVC中View會直接從Model中讀取數據而不是通過 Controller。
首先我們先看下傳統的MVC架構Model View Controller,我們把業務邏輯放到C層(ios的ViewController,android的Activity&Fragment),但是這里會引入另外一個問題,所有的邏輯都在C層,不可避免的會造成C層非常復雜,如果項目越來越大,C層的代碼會更加臃腫,維護起來也非常麻煩,而且也沒辦法==簡單的==做單元測試,試想做一個單元測試我們要加入多少邏輯代碼?


綜上所述我們總結下,現有的MVC模式存在以下問題:

視圖與控制器間的過于緊密的連接

視圖與控制器是相互分離,但卻是聯系緊密的部件,視圖沒有控制器的存在,其應用是很有限的,反之亦然,這樣就妨礙了他們的獨立重用。

視圖對模型數據的低效率訪問

依據模型操作接口的不同,視圖可能需要多次調用才能獲得足夠的顯示數據。對未變化數據的不必要的頻繁訪問,也將損害操作性能。

不太友好的單元測試

特別是App上做單元測試的時候很多東西依賴與系統框架,沒法脫離用戶接口來測試這些邏輯單元。使用MVP對Presenter的測試--不需要使用自動化的測試工具。 我們可以在Model和View都沒有完成時候,就可以通過編寫Mock Object(即實現了Model和View的接口,但沒有具體的內容的)來測試Presenter的邏輯。

基于以上幾點問題,就衍生了出了一些軟件設計模式如MVP,MVVW。為什么是MVP?我們先看下面這張圖


MVP分離了view和model層,Presenter層充當了橋梁的角色,View層只負責更新界面即可,這里的View我們要明白只是一個viewinterface,它是視圖的接口,這樣我們在做單元測試的時候可以非常方便編寫Presenter層代碼。關于mvp的代碼測試,我們可以參考google給出的代碼,google現在也在推行mvp,為此google發布了一些案例,大家可參考這里android-architecture


厚重的Controller層代碼也得到了釋放,之前我們開發的時候會對UIViewController、Activity、Fragment編寫很多的業務邏輯,盡管大家會將Service層做分離,如net層,DB層等,但還是無法避免類似的問題,activity uicontroller無法重復利用是非常難以忍受的。
有一點還需要注意,presenter是雙向綁定的關系,因此,在設計的時候就要注意接口和抽象的使用,盡可能的降低代碼的耦合度,這也是mvp的宗旨。

so,轉向mvp吧!我們先看下MVP幾個單詞的意思,以下是我個人的理解:

View: 是顯示數據(model)并且將用戶指令(events)傳送到presenter以便作用于那些數據的一個接口。View通常含有Presenter的引用。在Android開發中通常將Activity或者Fragment作為View層。

Model: 對于Model層也是數據層。它區別于MVC架構中的Model,在這里不僅僅只是數據模型。在MVP架構中Model它負責對數據的存取操作,例如對數據庫的讀寫,網絡的數據的請求等。

Presenter:對于Presenter層他是連接View層與Model層的橋梁并對業務邏輯進行處理。在MVP架構中Model與View無法直接進行交互。所以在Presenter層它會從Model層獲得所需要的數據,進行一些適當的處理后交由View層進行顯示。這樣通過Presenter將View與Model進行隔離,使得View和Model之間不存在耦合,同時也將業務邏輯從View中抽離。

三.實例

接下來我們看一個使用的用例吧,這個demo相對來說非常簡單,下面是項目的架構,一個Activity,一個Fragment,Data層主要負責獲取App已安裝的應用列表,AppListPresenter負責業務邏輯處理


我們先看下presenter,viewinterface的結構。


AppListFragment的代碼

 1   public class AppListFragment extends Fragment implements AppViewInterface {
 2 
 3         private Presenter presenter;
 4 
 5         private List<PackageInfo> packageInfoList = new ArrayList<>();
 6         private RecyclerView recyclerView;
 7         private MyAppListRecyclerViewAdapter myAppListRecyclerViewAdapter;
 8 
 9         @Override
10         public void showAppList(List<PackageInfo> packageInfos) {
11             if (packageInfos.isEmpty())
12                 return;
13             packageInfoList.clear();
14             packageInfoList.addAll(packageInfos);
15             myAppListRecyclerViewAdapter.notifyDataSetChanged();
16         }
17 
18         @Override
19         public void setPresenter(Presenter presenter) {
20             this.presenter = presenter;
21         }
22     }

 

代碼比較容易理解,AppListFragment實現了AppViewInterface接口,我們需要在Activity中把AppListPresenter和AppViewInterface雙向綁定。

接下來看下AppListPresenter層的代碼,這里只列出了幾個關鍵方法

 1     public class AppListPresenter implements Presenter, LoaderManager.LoaderCallbacks<List<PackageInfo>>{
 2 
 3         private AppViewInterface viewInterface;
 4         private AppClassLoader appClassLoader;
 5         private LoaderManager loaderManager;
 6 
 7         private final int id = 0;
 8         public AppListPresenter(AppViewInterface viewInterface, AppClassLoader appClassLoader, 
 9                         LoaderManager loaderManager) {
10             this.viewInterface = viewInterface;
11             this.appClassLoader = appClassLoader;
12             this.loaderManager = loaderManager;
13             viewInterface.setPresenter(this);
14         }
15 
16         @Override
17         public void loadInstallApps() {
18             //通過loadmanager提供的方法獲取安裝的應用列表
19             loaderManager.initLoader(id, null, this);
20         }
21 
22         @Override
23         public void destory() {
24             loaderManager.destroyLoader(id);
25         }
26 
27         @Override
28         public void onLoadFinished(Loader<List<PackageInfo>> loader, List<PackageInfo> data) {
29             //獲取到已安裝的應用列表,調用AppViewInterface的showAppList方法
30             viewInterface.showAppList(data);
31         }
32 
33         @Override
34         public void launchApp(PackageInfo packageInfo) {
35             Intent intent = appClassLoader.queryLaunchIntent(packageInfo);
36             if (intent != null)
37                 appClassLoader.getContext().startActivity(intent);
38             else
39                 Toast.makeText(appClassLoader.getContext(), "Can not start the app", Toast.LENGTH_SHORT).show();
40         }
41     }

  

關鍵方法是loadInstallApps,這個方法在MainActivity的onCreate中調用

 1     private Presenter appListPresenter;
 2 
 3     @Override
 4     protected void onCreate(Bundle savedInstanceState) {
 5         super.onCreate(savedInstanceState);
 6 
 7         setContentView(R.layout.activity_main);
 8 
 9         Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
10         setSupportActionBar(toolbar);
11 
12         FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
13         AppListFragment appListFragment = AppListFragment.newInstance();
14         fragmentTransaction.add(R.id.fm, appListFragment);
15         fragmentTransaction.commit();
16 
17         appListPresenter = new AppListPresenter(appListFragment, new AppClassLoader(getApplicationContext()), 
18                                             getSupportLoaderManager());
19         //調用loadInstallApps
20         appListPresenter.loadInstallApps();
21     }

首先,我們獲取一個AppListFragment的實例,在AppListPresenter構造函數里面我們傳入AppViewInterface,同時在AppPresenter的構造函數中又將presenter注入到了AppViewInerface里面,這樣就實現了Presenter和ViewInerface雙向綁定,之后調用AppPresenter的loadInstallApps方法,在onLoadFinished回調里面又調用了AppViewInterface的showApps方法,這樣數據就顯示在界面。整個Activity和Fragment的代碼精簡了很多。

四.缺點

由于對視圖的渲染放在了Presenter中,所以視圖和Presenter的交互會過于頻繁。還有一點需要明白,如果Presenter過多地渲染了視圖,往往會使得它與特定的視圖的聯系過于緊密。一旦視圖需要變更,那么Presenter也需要變更了

作者:萌蠢的技術宅
鏈接:https://www.jianshu.com/p/4b754ea48a40
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

總結

以上是生活随笔為你收集整理的MVP架构模式详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。