Dagger2 - 深刻(mvp 結合使用)

背景

mvp話說也出來好久了,初入學習Dagger的時候,就感受和mvp結合能更加有效的解決presenter注入的的問題,避免更多的代碼複寫!並且大概看了下網絡上的資源,通常可能是分開講解dagger和mvp技術,結合使用的不多,因此決定寫出來和你們一塊兒學習!html


何爲MVP

MVP,全稱 Model-View-Presenter,要說MVP那就不得不說一說它的前輩MVC。
MVC(Model-View-Controller,模型-視圖-控制器)模式是80年代Smalltalk-80出現的一種軟件設計模式,後來獲得了普遍的應用,其主要目的在於促進應用中模型,視圖,控制器間的關注的清晰分離。MVP(Model-View-Presenter,模型-視圖-表示器)模式則是由IBM開發出來的一個針對C++和Java的編程模型,大概出現於2000年,是MVC模式的一個變種,主要用來隔離UI、UI邏輯和業務邏輯、數據。也就是說,MVP 是從經典的模式MVC演變而來,它們的基本思想有相通的地方:Controller/Presenter負責邏輯的處理,Model提供數據,View負責顯示,全部通訊都是單向的;java

這裏寫圖片描述

MVP 模式將 Controller 更名爲 Presenter,同時改變了通訊方向git

這裏寫圖片描述

  • 一、各部分之間的通訊,都是雙向的。github

  • 二、View 與 Model 不發生聯繫,都經過 Presenter 傳遞。編程

  • 三、 View 很是薄,不部署任何業務邏輯,稱爲"被動視圖"(Passive View),即沒有任何主動性,而 Presenter很是厚,全部邏輯都部署在那裏。設計模式

    所以咱們能夠發現MVP的優勢以下:網絡

  • 一、模型與視圖徹底分離,咱們能夠修改視圖而不影響模型;ide

  • 二、能夠更高效地使用模型,由於全部的交互都發生在一個地方——Presenter內部;單元測試

  • 三、咱們能夠將一個Presenter用於多個視圖,而不須要改變Presenter的邏輯。這個特性很是的有用,由於視圖的變化老是比模型的變化頻繁;學習

  • 四、若是咱們把邏輯放在Presenter中,那麼咱們就能夠脫離用戶接口來測試這些邏輯(單元測試)。

具體到Android App中,通常能夠將App根據程序的結構進行縱向劃分,根據MVP能夠將App分別爲模型層(M),UI層(V)和邏輯層(P)。

UI層通常包括Activity,Fragment,Adapter等直接和UI相關的類,UI層的Activity在啓動以後實例化相應的Presenter,App的控制權後移,由UI轉移到Presenter,二者之間的通訊經過BroadCast、Handler或者接口完成,只傳遞事件和結果。

舉個簡單的例子,UI層通知邏輯層(Presenter)用戶點擊了一個Button,邏輯層(Presenter)本身決定應該用什麼行爲進行響應,該找哪一個模型(Model)去作這件事,最後邏輯層(Presenter)將完成的結果更新到UI層


MVP實現

如何把mvp實如今咱們的代碼上呢?

這裏寫圖片描述

能夠從上面簡單的demo的結構上看出,model和ui層都是提供了一個外部接口類,而presenter擁有這兩個類的依賴,而MvpActivity擁有presenter的依賴,當MvpActivity觸發事件後經過presenter觸發事件處理model,當model處理完成之後經過ui外部接口類回調給activity!


構建

1.構建ui接口類

定義事件方法

public interface MvpUiImpl {
   void showTest(String msg);
}複製代碼

2.activity實現接口類

public class MvpActivity extends AppCompatActivity implements MvpUiImpl{

    MvpPresenter presenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mvp);

        findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                presenter.testDoS();
            }
        });
    }

    @Override
    public void showTest(String msg) {
        TextView tv=(TextView)findViewById(R.id.tv);
        tv.setText(msg);
    }
}複製代碼

3.model接口類

model接口定義處理數據方法

public interface MvpModelImpl {
    MvpEntity test();
}複製代碼

4.model具體實現類

實現具體的數據處理方法

public class MvpModel implements MvpModelImpl{

    @Override
    public MvpEntity test() {
        return new MvpEntity("數據");
    }
}複製代碼

presenter處理核心類

經過ui和model對象的引用對象,事件觸發後調用數據model處理方法,成功後回調給ui界面

public class MvpPresenter {
    MvpUiImpl ui;
    MvpModelImpl model;

    public MvpPresenter(MvpUiImpl ui, MvpModelImpl model) {
        this.ui = ui;
        this.model = model;
    }

    public void testDoS() {
        MvpEntity entity = model.test();
        ui.showTest(entity.getMsg());
    }

}複製代碼

經過上面簡單的構建,到這裏一個傳統的mvp構建就算是完成了!可是 MvpPresenter類初始化須要傳遞的兩個依賴對象,這裏正好咱們可使用dagger2的依賴注入實現MvpPresenter,減小程序的耦合度!


Dagger構建mvp

Dagger在mvp中的運用主要是優化Presenter建立依賴對象,因此開始咱們的優化!

1.建立MvpPresenterModule

既然須要獲得一個Presenter,首先須要構建一個對應的module

@PerApp
@Module
public class MvpPresenterModule {
    private MvpActivity activity;

    public MvpPresenterModule(MvpActivity activity) {
        this.activity = activity;
    }

    @Provides
    MvpActivity provideActivity(){
        return  activity;
    }

    @Provides
    MvpPresenter providePresenter(MvpActivity ui,MvpModel mvpModel){
        return new MvpPresenter(ui,mvpModel);
    }

    @Provides
    MvpModel provideMvpModel(){
        return new MvpModel();
    }
}複製代碼

注意:看完這段代碼估計有同窗發現,和以前的model構建好像不同呀,對!這裏咱們在MvpPresenterModule 中首先提供了兩個@Provides定義的方法,一個方法提供了MvpActivity ,另外一個提供了一個MvpModel 對象;而這兩個不正式初始MvpPresenter的依賴注入對象嘛!
是的這裏咱們經過dagger自帶的@Provides方法,首先提供了兩個MvpPresenter初始須要的對象,而後在@Provides定義一個MvpPresenter providePresenter(MvpActivity ui,MvpModel mvpModel)方法,讓Dagger自動爲咱們建立一個MvpPresenter 對象

2.構建Component

和傳統Dagger構建同樣,Component定義依賴的model,inject定義消耗的activity對象

@PerApp
@Singleton
@Component(modules = MvpPresenterModule.class)
public interface MvpPresenterComponent {

    void inject(MvpActivity activity);

}複製代碼

3.activity注入依賴

public class MvpActivity extends AppCompatActivity implements MvpUiImpl{
    @Inject
    MvpPresenter presenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mvp);
        MvpPresenterComponent component= DaggerMvpPresenterComponent.builder().mvpPresenterModule(new MvpPresenterModule(this))
             .build();
        component.inject(this);

        findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                presenter.testDoS();
            }
        });
    }

    @Override
    public void showTest(String msg) {
        TextView tv=(TextView)findViewById(R.id.tv);
        tv.setText(msg);
    }
}複製代碼

結果

這裏寫圖片描述

若有幫助歡迎start和留言!


專欄

註解專欄


源碼

傳送門-Github

傳送門-CSDN


建議

若是你有任何的問題和建議歡迎加入QQ羣告訴我!

相關文章
相關標籤/搜索