MVP模式的核心思想:
MVP把Activity中的UI邏輯抽象成View接口,把業務邏輯抽象成功接口,Model類還是原來的Model。
MVC
- 其中View層其實就是程序的UI界面,用於向用戶展示數據以及接收用戶的輸入
- 而Model層就是JavaBean實體類,用於保存實例數據
- Controller控制器用於更新UI界面和數據實例
View層接受用戶的輸入,然后通過Controller修改對應的Model實例;同時,當Model實例的數據發生變化的時候,需要修改UI界面,可以通過Controller更新界面。View層也可以直接更新Model實例的數據,而不用每次都通過Controller,這樣對於一些簡單的數據更新工作會變得方便許多。
MVP
MVP與MVC最不同的一點是M與V是不直接關聯的也是就Model與View不存在直接關系,這兩者之間間隔着的是Presenter層
Model
Model 是用戶界面需要顯示數據的抽象,也可以理解為從業務數據(結果)那里到用戶界面的抽象(Business rule, data access, model classes)
View
視圖這一層體現的很輕薄,負責顯示數據、提供友好界面跟用戶交互就行。MVP下Activity和Fragment體現在了這一層,Activity一般也就做加載UI視圖、設置監聽再交由Presenter處理的一些工作,所以也就需要持有相應Presenter的引用。例如,Activity上滾動列表時隱藏或者顯示Acionbar(Toolbar),這樣的UI邏輯時也應該在這一層。另外在View上輸入的數據做一些判斷時,例如,EditText的輸入數據,假如是簡單的非空判斷則可以作為View層的邏輯,而當需要對EditText的數據進行更復雜的比較時,如從數據庫獲取本地數據進行判斷時明顯需要經過Model層才能返回了,所以這些細節需要自己掂量。
Presenter
Presenter這一層處理着程序各種邏輯的分發,收到View層UI上的反饋命令、定時命令、系統命令等指令后分發處理邏輯交由業務層做具體的業務操作,然后將得到的 Model 給 View 顯示。
這就是MVP模式,現在這樣的話,Activity的工作的簡單了,只用來響應生命周期,其他工作都丟到Presenter中去完成。從上圖可以看出,Presenter是Model和View之間的橋梁,為了讓結構變得更加簡單,View並不能直接對Model進行操作,這也是MVP與MVC最大的不同之處。
優點
- 分離了視圖邏輯和業務邏輯,降低了耦合
- Activity只處理生命周期的任務,代碼變得更加簡潔
- 視圖邏輯和業務邏輯分別抽象到了View和Presenter的接口中去,提高代碼的可閱讀性
- Presenter被抽象成接口,可以有多種具體的實現,所以方便進行單元測試
- 把業務邏輯抽到Presenter中去,避免后台線程引用着Activity導致Activity的資源無法被系統回收從而引起內存泄露和OOM
代碼變得更加簡潔
使用MVP之后,Activity就能瘦身許多了,基本上只有FindView、SetListener以及Init的代碼。其他的就是對Presenter的調用,還有對View接口的實現。這種情形下閱讀代碼就容易多了,而且你只要看Presenter的接口,就能明白這個模塊都有哪些業務,很快就能定位到具體代碼。Activity變得容易看懂,容易維護,以后要調整業務、刪減功能也就變得簡單許多。
方便進行單元測試
MVP中,由於業務邏輯都在Presenter里,我們完全可以寫一個PresenterTest的實現類繼承Presenter的接口,現在只要在Activity里把Presenter的創建換成PresenterTest,就能進行單元測試了,測試完再換回來即可。萬一發現還得進行測試,那就再換成PresenterTest吧。
避免內存泄露
Android APP 發生OOM的最大原因就是出現內存泄露造成APP的內存不夠用,而造成內存泄露的兩大原因之一就是Activity泄露(Activity Leak)(另一個原因是Bitmap泄露(Bitmap Leak))
Java一個強大的功能就是其虛擬機的內存回收機制,這個功能使得Java用戶在設計代碼的時候,不用像C++用戶那樣考慮對象的回收問題。然而,Java用戶總是喜歡隨便寫一大堆對象,然后幻想着虛擬機能幫他們處理好內存的回收工作。可是虛擬機在回收內存的時候,只會回收那些沒有被引用的對象,被引用着的對象因為還可能會被調用,所以不能回收。
Activity是有生命周期的,用戶隨時可能切換Activity,當APP的內存不夠用的時候,系統會回收處於后台的Activity的資源以避免OOM。
采用傳統的MV模式,一大堆異步任務和對UI的操作都放在Activity里面,比如你可能從網絡下載一張圖片,在下載成功的回調里把圖片加載到 Activity 的 ImageView 里面,所以異步任務保留着對Activity的引用。這樣一來,即使Activity已經被切換到后台(onDestroy已經執行),這些異步任務仍然保留着對Activity實例的引用,所以系統就無法回收這個Activity實例了,結果就是Activity Leak。Android的組件中,Activity對象往往是在堆(Java Heap)里占最多內存的,所以系統會優先回收Activity對象,如果有Activity Leak,APP很容易因為內存不夠而OOM。
采用MVP模式,只要在當前的Activity的onDestroy里,分離異步任務對Activity的引用,就能避免 Activity Leak。
MVP 使用
MVP的主要特點就是把Activity里的許多邏輯都抽離到View和Presenter接口中去,並由具體的實現類來完成。
- 創建IPresenter接口,把所有業務邏輯的接口都放在這里,並創建它的實現PresenterCompl(在這里可以方便地查看業務功能,由於接口可以有多種實現所以也方便寫單元測試),IPresenter持有 IView,調用 IView 中的方法
- 創建IView接口,把所有視圖邏輯的接口都放在這里,其實現類是當前的Activity/Fragment
- 由UML圖可以看出,Activity里包含了一個IPresenter,而PresenterCompl里又包含了一個IView並且依賴了Model。Activity里只保留對IPresenter的調用,其它工作全部留到PresenterCompl中實現
- Model並不是必須有的,但是一定會有View和Presenter
DMEO
- 登陸 view 接口
1 |
package io.github.xuyushi.androidmvpdemo.Login.view; |
登陸Presenter接口
1 |
package io.github.xuyushi.androidmvpdemo.Login.presenter; |
實現Presenter接口
1 |
package io.github.xuyushi.androidmvpdemo.Login.presenter; |
定義model
1 |
package io.github.xuyushi.androidmvpdemo.Login.model; |
在 Activity 中實現 view接口
1 |
package io.github.xuyushi.androidmvpdemo.Login.view; |




