日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

一个简单的MVP模式案例

發(fā)布時(shí)間:2024/9/21 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一个简单的MVP模式案例 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1. 問題背景

首先需要清楚的一點(diǎn)是MVP模式的設(shè)計(jì)初衷是:為了解決在MVC模式中,過于復(fù)雜的邏輯和界面之間的交互中Activity的職責(zé)不單一的問題,Activity既充當(dāng)了View層,又充當(dāng)了Controller層的角色。刨除問題的復(fù)雜度,直接談MVP模式的優(yōu)越性,都是耍流氓。

這也就是為什么我們很多人,為什么不愿意學(xué)習(xí)MVP的原因。但是如果遇到了一個(gè)比較復(fù)雜的問題,MVP的解耦能夠讓你更加輕松地應(yīng)對(duì)需求的迭代。

本文將一個(gè)案例來解釋MVP模式的設(shè)計(jì)方法,但是這里有一個(gè)矛盾點(diǎn):MVP模式本身應(yīng)該作用于較復(fù)雜問題的,但是本文作為入門文章又必須使用一個(gè)較簡(jiǎn)單的場(chǎng)景去設(shè)計(jì),這樣才能容易看出MVP的結(jié)構(gòu)。

場(chǎng)景描述如下:

APP中有一本書(Model),書本的價(jià)格會(huì)顯示在Activity(View)中,Activity中有兩個(gè)按鈕,可以對(duì)書本的價(jià)格進(jìn)行控制(Presenter)。

2. MVP模式的實(shí)現(xiàn)

基于上面提出的場(chǎng)景,我們先簡(jiǎn)單的設(shè)計(jì)界面:

<?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="漲價(jià)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="降價(jià)1元"app:layout_constraintLeft_toRightOf="@id/increase"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="@id/increase"/></android.support.constraint.ConstraintLayout> 復(fù)制代碼

我們?cè)O(shè)計(jì)書本的數(shù)據(jù)模型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;}@Overridepublic 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();} } 復(fù)制代碼

Activity只負(fù)責(zé)顯示書本的信息,不參與漲價(jià)/降價(jià)的邏輯處理,所以我們需要?jiǎng)?chuàng)建一個(gè)Presenter類,把價(jià)格邏輯交給他處理,處理完之后再在Activity中顯示。

Presenter類應(yīng)該具有漲價(jià)/降價(jià)的能力,因此我們把Presenter設(shè)計(jì)成接口更加合理。IPresenter.java的內(nèi)容如下:

public interface IPresenter {void increasePrice();void decreasePrice(); } 復(fù)制代碼

再設(shè)計(jì)一個(gè)PresenterImpl類繼承IPresenter接口,并實(shí)現(xiàn)漲價(jià)和降價(jià)的兩個(gè)方法。因?yàn)樾枰赑resenter中操作Model,并在View中顯示,所以Presenter需要持有Model和View的對(duì)象。Model對(duì)象很簡(jiǎn)單,直接將BookVo傳給Presenter即可,但是View對(duì)象如何處理呢?

我們制定一個(gè)IView接口,向Presenter暴露我們能夠提供的能力,比如這個(gè)場(chǎng)景里的顯示書籍信息,于是IView接口內(nèi)容如下:

public interface IView {void showBookInfo(BookVo vo); } 復(fù)制代碼

我們讓MainActivity實(shí)現(xiàn)IView接口,

@Override public void showBookInfo(BookVo vo) {this.mDescTv.setText(vo.toString()); } 復(fù)制代碼

現(xiàn)在我們只需要給Presenter添加一個(gè)構(gòu)造方法就行,構(gòu)造方法中添加兩個(gè)參數(shù):BookVo和IView對(duì)象。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", " ---> 漲價(jià)了一元");mBookVo.setPrice(mBookVo.getPrice() + 1);this.mIView.showBookInfo(mBookVo);}@Overridepublic void decreasePrice() {Log.i("lxc", " ---> 降價(jià)了一元");mBookVo.setPrice(mBookVo.getPrice() - 1);this.mIView.showBookInfo(mBookVo);} } 復(fù)制代碼

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("《百年孤獨(dú)》");vo.setAuthor("泰戈?duì)?#34;);vo.setPrice(100);}private void initPresenter() {mPresenter = new PresenterImpl(this, vo);}@Overridepublic void showBookInfo(BookVo vo) {this.mDescTv.setText(vo.toString());} } 復(fù)制代碼

現(xiàn)在就可以看到效果了。

3.若干思考

  • MVP與MVC有什么區(qū)別?有本質(zhì)區(qū)別么?
  • 案例中P層和M層為什么要設(shè)計(jì)成接口?
  • 4. 后續(xù)

    本文中的Demo源碼和思考答案將存在于我的微信公眾號(hào)中,獲取源碼(Source)請(qǐng)回復(fù)"S2",獲取答案(Answer)請(qǐng)回復(fù)"A2"。另外歡迎大家關(guān)注我的微信公眾號(hào)~么么么

    總結(jié)

    以上是生活随笔為你收集整理的一个简单的MVP模式案例的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。