一葵姥、什么是MVP模式榔幸?
MVP是MVC的變種削咆,也是一種升級拨齐。要說MVP就要說說MVC瞻惋,在MVC中Activity其實(shí)就是View層級歼狼,但是通常在使用中Activity也是Contrloller,并沒有將View層和Controller層進(jìn)行分離限寞,耦合度大大提高履植,非常不利于項(xiàng)目的管理玫霎。所以也就產(chǎn)生了MVP。
二、MVC反番、MVP罢缸、MVVM區(qū)別和應(yīng)用建議
類型 | 創(chuàng)建過程 | 特點(diǎn) | 缺點(diǎn) | 應(yīng)用建議 |
---|---|---|---|---|
MVC | C->M+V | 分離了Model和Controller | Controller變得越來越復(fù)雜 | 簡單的枫疆、不大修改的頁面 |
MVP | V->P->M | 在MVC的基礎(chǔ)上通過接口徹底分離了View和Model | Presenter與View的交互變得瑣碎而復(fù)雜 | 核心息楔、復(fù)雜值依、需求變更更快頁面 |
MVVM | v->VM->M | 在MVP的基礎(chǔ)上增加了DataBinding,代碼量更小 | XML中包含代碼蟆淀,定位問題麻煩 | 核心、復(fù)雜疑苔、需求變更快頁面 |
三惦费、MVP架構(gòu)設(shè)計(jì)
1. MVP三個(gè)角色
- View
- Presenter
- Model
2. 設(shè)計(jì)思想
MVP把Activity中的UI邏輯抽象成View接口薪贫,把業(yè)務(wù)邏輯抽象成Presenter接口扯夭,Model層依然還是Model層交洗。
在MVP模式中Activity的功能就是響應(yīng)生命周期和顯示界面,具體的邏輯在Presenter中完成梁棠,Presenter是Model和View層的橋梁,這樣就把Model和View進(jìn)行了隔離盐碱。
3. 如何設(shè)計(jì)
以下是我的項(xiàng)目中MVP模式的使用類圖:
圖中有幾點(diǎn)需要注意:
- GankFragment直接依賴GankPresenter的實(shí)例围橡,后面可以用Dagger進(jìn)行解藕拣播;
- GankPresenter依賴IModel塞赂,IView,面向接口接口編程。GankModel圆存,GankPresenter叼旋,GankFragment分別實(shí)現(xiàn)各自的接口,IGankContract統(tǒng)一管理三者的接口沦辙,從而更方便了解P與M夫植,P與V之間的調(diào)用關(guān)系。
- GankModel不直接封裝數(shù)據(jù)層怕轿,而是依賴對應(yīng)提供數(shù)據(jù)API的接口偷崩,面向接口編程,所以就不用關(guān)心底層提供數(shù)據(jù)的方式撞羽。實(shí)現(xiàn)各自接口的Impl實(shí)現(xiàn)類就可以實(shí)現(xiàn)二次封裝阐斜,隨時(shí)可以替換底層開源庫。
4. RxJava+Retrofit的理解以及在MVP模式中使用
5. 理解注解以及Dagger
6. 在MVP模式中使用Dagger
在MVP模式中诀紊,因?yàn)镸谒出、V、P三個(gè)角色都可能存在直接的依賴引用邻奠,所以在修改某個(gè)角色的時(shí)候笤喳,可能也需要修改另外一個(gè)依賴方。
比如在View層中有依賴Presenter碌宴,通過利用Dagger2就可以解除兩者的依賴杀狡。
public class MainActivity extends AppCompatActivity implements MainContract.View {
@Inject
MainPresenter mainPresenter;
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerMainComponent.builder()
.mainModule(new MainModule(this))
.build()
.inject(this);
//調(diào)用Presenter方法加載數(shù)據(jù)
mainPresenter.loadData();
...
}
}
public class MainPresenter {
//MainContract是個(gè)接口,View是他的內(nèi)部接口贰镣,這里看做View接口即可
private MainContract.View mView;
@Inject
MainPresenter(MainContract.View view) {
mView = view;
}
public void loadData() {
//調(diào)用model層方法呜象,加載數(shù)據(jù)
...
//回調(diào)方法成功時(shí)
mView.updateUI();
}
@Module
public class MainModule {
private final MainContract.View mView;
public MainModule(MainContract.View view) {
mView = view;
}
@Provides
MainView provideMainView() {
return mView;
}
}
@Component(modules = MainModule.class)
public interface MainComponent {
void inject(MainActivity activity);
}
對應(yīng)項(xiàng)目地址:https://github.com/liuhe1993/myproject