【Android - 框架】之MVP模式的使用


  提起MVP架構模式,大家可能首先想到的是它的“前輩”MVC模式。MVC由Model、View、Controller組成,請求從Controller進入后進行業務判斷,然后交給Model或View進行處理。這本身沒什么,但是應用在Android程序中時,大家就會發現,Activity既擔任了Controller的角色進行業務篩選,又擔任了View的角色進行界面展示,甚至有些時候還會擔任Model的角色加載數據。這就使的Activity中的代碼變得很多很長,而且功能雜亂,不便區分。怎么辦呢?於是,MVP模式就誕生了。

  MVP由Model、View和Presenter組成,和MVC相似,MVP中的Model層也是用來加載數據的,View層也是用來展示界面的,MVP中獨有的Presenter是用來連接Model和View兩層,起到解耦的作用。下圖展示了MVC模式和MVP模式的工作流程上的比較:

  從圖中可以看到,MVP模式中的View層和Model層之間沒有連線,即這兩層之間沒有直接的關聯,它們之間的交互是通過Presenter來完成的,這樣就實現的View和Model兩層的解耦。具體的MVP內部的工作流程如下圖所示:

  可以看到,用戶首先在View層中進行操作,將用戶動作傳到Presenter中,Presenter將動作傳遞到Model中進行處理,然后將處理結果傳回到Presenter,再由Presenter相應到View中。

  MVP模式的整體架構是通過接口來搭建的,我們需要一個整體的架構管理類Contract來管理Model、View、Presenter這三個接口,Model類、View類和Presenter類都分別實現這三個接口。Presenter中持有Model和View的引用,Presenter中的所有方法都會調用Model中對應的方法進行處理;Model中寫實際代碼;View是被Activity實現的,其中持有一個Presenter的引用,所有方法都會調用Presenter的對應方法。

  下面貼出一個簡單的DEMO中的代碼。

  DEMO的界面非常簡單,只有一個按鈕,當我們點擊按鈕的時候彈出一個Toast,就是這么一個簡單的DEMO,我們嘗試用MVP模式來搭建,編寫。

  首先我們需要一個接口的統一管理類MainContract,這個類中包含了M、V、P三個接口,接口中定義抽象方法。這里我們只打算有一個方法,即按鈕點擊事件onButtonClicked()方法。代碼如下:

public class MainContract {

    interface View {
        void onButtonClicked(String text);
    }

    interface Model {
        void onButtonClicked(Context context, String text);
    }

    interface Presenter {
        void onButtonClicked(Context context, String text);
    }
}

  有了接口之后,我們讓M、V、P三層的具體類來實現這三個接口,這三個類分別是:M層對應MainModel,P層對應MainPresenter,V層對應MainActivity。

  我們來編寫MainPresenter類中的代碼,首先需要讓它實現MainContract類中的Presenter接口,然后為它設置兩個屬性,一個是Model,一個是View,在構造方法中傳入View,並初始化Model,最后實現Presenter接口中的方法並調用Model中的對應方法實現。MainPresenter類中的代碼如下:

public class MainPresenter implements MainContract.Presenter {
    private MainContract.Model model;
    private MainContract.View view;

    public MainPresenter(MainContract.View view) {
        this.view = view;
        this.model = new MainModel();
    }

    @Override
    public void onButtonClicked(Context context, String text) {
        model.onButtonClicked(context, text);
    }
}

  接下來是MainModel類中的代碼了。MVP中的所有具體邏輯實現的代碼都是在Model層中編寫的,因此在MainModel實現Model接口的onButtonClicked()方法中,我們按照需求彈出一個Toast即可。代碼如下:

public class MainModel implements MainContract.Model {
    @Override
    public void onButtonClicked(Context context, String text) {
        Toast.makeText(context, text, Toast.LENGTH_SHORT).show();
    }
}

  最后就是View層的編寫了。上面說過,View層的實現類就是Activity,View層中需要持有一個Presenter的引用,View層中的所有操作都調用Presenter層中對應的方法,而Presenter層都是調用Model層的代碼,因此View層就算是間接的調用了Model層的代碼。MainActivity中的代碼如下:

public class MainActivity extends AppCompatActivity implements MainContract.View {
    private MainPresenter presenter = new MainPresenter(MainActivity.this);

    @InjectView(R.id.btn)
    protected Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 初始化ButterKnife
        ButterKnife.inject(MainActivity.this);
    }

    @OnClick(R.id.btn)
    protected void click() {
        onButtonClicked("Button Clicked!!!!");
    }

    @Override
    public void onButtonClicked(String text) {
        presenter.onButtonClicked(MainActivity.this, text);
    }
}

  到此為止,MVP的一個簡單的DEMO就完成了。MVP只是一種思路,每個人都有每個人的理解,因此架構的搭建會有所不同,但整體的目標是不變的,那就是讓Activity中的View層和Controller層分離開來,減少Activity中的代碼。

  當然,MVP模式也有缺點,那就是每創建一個Activity,就需要再創建Contract、Model、Presenter三個類,會大大增加項目中的類的個數。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM