一个简单的MVP模式案例
1. 問題背景
首先需要清楚的一點是MVP模式的設計初衷是:為了解決在MVC模式中,過于復雜的邏輯和界面之間的交互中Activity的職責不單一的問題,Activity既充當了View層,又充當了Controller層的角色。刨除問題的復雜度,直接談MVP模式的優越性,都是耍流氓。
這也就是為什么我們很多人,為什么不愿意學習MVP的原因。但是如果遇到了一個比較復雜的問題,MVP的解耦能夠讓你更加輕松地應對需求的迭代。
本文將一個案例來解釋MVP模式的設計方法,但是這里有一個矛盾點:MVP模式本身應該作用于較復雜問題的,但是本文作為入門文章又必須使用一個較簡單的場景去設計,這樣才能容易看出MVP的結構。
場景描述如下:
APP中有一本書(Model),書本的價格會顯示在Activity(View)中,Activity中有兩個按鈕,可以對書本的價格進行控制(Presenter)。
2. MVP模式的實現
基于上面提出的場景,我們先簡單的設計界面:
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.orzangleli.mvpdemo.MainActivity"><TextViewandroid:id="@+id/desc"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="Hello World!"android:textSize="16dp"android:gravity="center_vertical"android:padding="5dp"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent"/><Buttonandroid:id="@+id/increase"android:layout_width="0dp"android:layout_height="wrap_content"android:text="漲價1元"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toLeftOf="@+id/decrease"app:layout_constraintTop_toBottomOf="@id/desc"android:layout_marginTop="60dp"/><Buttonandroid:id="@+id/decrease"android:layout_width="0dp"android:layout_height="wrap_content"android:text="降價1元"app:layout_constraintLeft_toRightOf="@id/increase"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="@id/increase"/></android.support.constraint.ConstraintLayout> 復制代碼我們設計書本的數據模型BookVo。
public class BookVo {private String name;private int price;private String author;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getPrice() {return price;}public void setPrice(int price) {this.price = price;}public String getAuthor() {return author;}public void setAuthor(String author) {this.author = author;}public String toString() {final StringBuffer sb = new StringBuffer("BookVo{");sb.append("name='").append(name).append('\'');sb.append(", price=").append(price);sb.append(", author='").append(author).append('\'');sb.append('}');return sb.toString();} } 復制代碼Activity只負責顯示書本的信息,不參與漲價/降價的邏輯處理,所以我們需要創建一個Presenter類,把價格邏輯交給他處理,處理完之后再在Activity中顯示。
Presenter類應該具有漲價/降價的能力,因此我們把Presenter設計成接口更加合理。IPresenter.java的內容如下:
public interface IPresenter {void increasePrice();void decreasePrice(); } 復制代碼再設計一個PresenterImpl類繼承IPresenter接口,并實現漲價和降價的兩個方法。因為需要在Presenter中操作Model,并在View中顯示,所以Presenter需要持有Model和View的對象。Model對象很簡單,直接將BookVo傳給Presenter即可,但是View對象如何處理呢?
我們制定一個IView接口,向Presenter暴露我們能夠提供的能力,比如這個場景里的顯示書籍信息,于是IView接口內容如下:
public interface IView {void showBookInfo(BookVo vo); } 復制代碼我們讓MainActivity實現IView接口,
@Override public void showBookInfo(BookVo vo) {this.mDescTv.setText(vo.toString()); } 復制代碼現在我們只需要給Presenter添加一個構造方法就行,構造方法中添加兩個參數:BookVo和IView對象。PresenterImpl.java代碼如下:
public class PresenterImpl implements IPresenter {private IView mIView;private BookVo mBookVo;public PresenterImpl(IView iView, BookVo vo) {this.mIView = iView;this.mBookVo = vo;}@Overridepublic void increasePrice() {Log.i("lxc", " ---> 漲價了一元");mBookVo.setPrice(mBookVo.getPrice() + 1);this.mIView.showBookInfo(mBookVo);}@Overridepublic void decreasePrice() {Log.i("lxc", " ---> 降價了一元");mBookVo.setPrice(mBookVo.getPrice() - 1);this.mIView.showBookInfo(mBookVo);} } 復制代碼MainActivity代碼如下:
public class MainActivity extends AppCompatActivity implements IView{private TextView mDescTv;private Button mIncreaseBtn, mDecreaseBtn;private IPresenter mPresenter;private BookVo vo;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initData();initPresenter();mDescTv = findViewById(R.id.desc);mIncreaseBtn = findViewById(R.id.increase);mDecreaseBtn = findViewById(R.id.decrease);mIncreaseBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {mPresenter.increasePrice();}});mDecreaseBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {mPresenter.decreasePrice();}});mDescTv.setText(vo.toString());}private void initData() {vo = new BookVo();vo.setName("《百年孤獨》");vo.setAuthor("泰戈爾");vo.setPrice(100);}private void initPresenter() {mPresenter = new PresenterImpl(this, vo);}@Overridepublic void showBookInfo(BookVo vo) {this.mDescTv.setText(vo.toString());} } 復制代碼現在就可以看到效果了。
3.若干思考
4. 后續
本文中的Demo源碼和思考答案將存在于我的微信公眾號中,獲取源碼(Source)請回復"S2",獲取答案(Answer)請回復"A2"。另外歡迎大家關注我的微信公眾號~么么么
總結
以上是生活随笔為你收集整理的一个简单的MVP模式案例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 14.11类的成员修饰符
- 下一篇: isinstance函数