MVP

Android MVP模式

  1. MVC模式 & 缺點
    MVC,全稱Model-View-Controller,即模型-視圖-控制器。 具體如下:
  • View:對應(yīng)于布局文件
  • Model:業(yè)務(wù)邏輯和實體模型
  • Controllor:對應(yīng)于Activity

缺點
MVC模式下實際上就是Activty與Model之間交互,View完全獨立出來了。
View對應(yīng)于布局文件,其實能做的事情特別少,實際上關(guān)于該布局文件中的數(shù)據(jù)綁定的操作,事件處理的代碼都在Activity中,造成了Activity既像View又像Controller,使得Activity變得臃腫。


在這里插入圖片描述
  1. MVP模式 & 優(yōu)點
    MVP,全稱 Model-View-Presenter,即模型-視圖-層現(xiàn)器。具體如下:
  • View 對應(yīng)于Activity,負(fù)責(zé)View的繪制以及與用戶交互
  • Model 依然是業(yè)務(wù)邏輯和實體模型
  • Presenter 負(fù)責(zé)完成View于Model間的交互

優(yōu)點
MVP模式通過Presenter實現(xiàn)數(shù)據(jù)和視圖之間的交互,簡化了Activity的職責(zé)。同時即避免了View和Model的直接聯(lián)系,又通過Presenter實現(xiàn)兩者之間的溝通。
MVP模式減少了Activity的職責(zé),簡化了Activity中的代碼,將復(fù)雜的邏輯代碼提取到了Presenter中進(jìn)行處理,模塊職責(zé)劃分明顯,層次清晰。與之對應(yīng)的好處就是,耦合度更低,更方便的進(jìn)行測試。


在這里插入圖片描述
  1. MVP & MVC 區(qū)別

    在這里插入圖片描述

    MVC中是允許Model和View進(jìn)行交互的,而MVP中很明顯,Model與View之間的交互由Presenter完成。還有一點就是Presenter與View之間的交互是通過接口的。

  2. MVP模式 典例 —— 登錄案例
    結(jié)構(gòu)圖

    在這里插入圖片描述

    1.Model層
    在本例中,M0del層負(fù)責(zé)對從登錄頁面獲取地帳號密碼進(jìn)行驗證(一般需要請求服務(wù)器進(jìn)行驗證,本例直接模擬這一過程)。 從上圖的包結(jié)構(gòu)圖中可以看出,Model層包含內(nèi)容:
    ①實體類bean
    ②接口,表示Model層所要執(zhí)行的業(yè)務(wù)邏輯
    ③接口實現(xiàn)類,具體實現(xiàn)業(yè)務(wù)邏輯,包含的一些主要方法
    下面以代碼的形式一一展開。
    ①實體類bean

public class User {
    private String password;
    private String username;

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @Override
    public String toString() {
        return "User{" +
                "password='" + password + '\'' +
                ", username='" + username + '\'' +
                '}';
    }
}

封裝了用戶名、密碼,方便數(shù)據(jù)傳遞。
②接口

public interface LoginModel {
    void login(User user, OnLoginFinishedListener listener);
}

其中OnLoginFinishedListener 是presenter層的接口,方便實現(xiàn)回調(diào)presenter,通知presenter業(yè)務(wù)邏輯的返回結(jié)果,具體在presenter層介紹。
③接口實現(xiàn)類

public class LoginModelImpl implements LoginModel {
    @Override
    public void login(User user, final OnLoginFinishedListener listener) {
        final String username = user.getUsername();
        final String password = user.getPassword();
        new Handler().postDelayed(new Runnable() {
            @Override public void run() {
                boolean error = false;
                if (TextUtils.isEmpty(username)){
                    listener.onUsernameError();//model層里面回調(diào)listener
                    error = true;
                }
                if (TextUtils.isEmpty(password)){
                    listener.onPasswordError();
                    error = true;
                }
                if (!error){
                    listener.onSuccess();
                }
            }
        }, 2000);
    }
}

實現(xiàn)Model層邏輯:延時模擬登陸(2s),如果用戶名或者密碼為空則登陸失敗,否則登陸成功。
2.View層
視圖:將Modle層請求的數(shù)據(jù)呈現(xiàn)給用戶。一般的視圖都只是包含用戶界面(UI),而不包含界面邏輯,界面邏輯由Presenter來實現(xiàn)。
從上圖的包結(jié)構(gòu)圖中可以看出,View包含內(nèi)容:
①接口,上面我們說過Presenter與View交互是通過接口。其中接口中方法的定義是根據(jù)Activity用戶交互需要展示的控件確定的。
②接口實現(xiàn)類,將上述定義的接口中的方法在Activity中對應(yīng)實現(xiàn)具體操作。
下面以代碼的形式一一展開。
①接口

public interface LoginView {
    //login是個耗時操作,我們需要給用戶一個友好的提示,一般就是操作ProgressBar
    void showProgress();

    void hideProgress();
   //login當(dāng)然存在登錄成功與失敗的處理,失敗給出提示
    void setUsernameError();

    void setPasswordError();
   //login成功,也給個提示
    void showSuccess();
}

上述5個方法都是presenter根據(jù)model層返回結(jié)果需要view執(zhí)行的對應(yīng)的操作。
②接口實現(xiàn)類
即對應(yīng)的登錄的Activity,需要實現(xiàn)LoginView接口。

public class LoginActivity extends AppCompatActivity implements LoginView, View.OnClickListener {
    private ProgressBar progressBar;
    private EditText username;
    private EditText password;
    private LoginPresenter presenter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        progressBar = (ProgressBar) findViewById(R.id.progress);
        username = (EditText) findViewById(R.id.username);
        password = (EditText) findViewById(R.id.password);
        findViewById(R.id.button).setOnClickListener(this);
       //創(chuàng)建一個presenter對象,當(dāng)點擊登錄按鈕時,讓presenter去調(diào)用model層的login()方法,驗證帳號密碼
        presenter = new LoginPresenterImpl(this);
    }

    @Override
    protected void onDestroy() {
        presenter.onDestroy();
        super.onDestroy();
    }

    @Override
    public void showProgress() {
        progressBar.setVisibility(View.VISIBLE);
    }

    @Override
    public void hideProgress() {
        progressBar.setVisibility(View.GONE);
    }

    @Override
    public void setUsernameError() {
        username.setError(getString(R.string.username_error));
    }

    @Override
    public void setPasswordError() {
        password.setError(getString(R.string.password_error));
    }

    @Override
    public void showSuccess() {
         progressBar.setVisibility(View.GONE);
        Toast.makeText(this,"login success",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onClick(View v) {
        User user = new User();
        user.setPassword(password.getText().toString());
        user.setUsername(username.getText().toString());
        presenter.validateCredentials(user);
    }

}

View層實現(xiàn)Presenter層需要調(diào)用的控件操作,方便Presenter層根據(jù)Model層返回的結(jié)果進(jìn)行操作View層進(jìn)行對應(yīng)的顯示。
3.Presenter層
Presenter是用作Model和View之間交互的橋梁。 從上圖的包結(jié)構(gòu)圖中可以看出,Presenter包含內(nèi)容:
①接口,包含Presenter需要進(jìn)行Model和View之間交互邏輯的接口,以及上面提到的Model層數(shù)據(jù)請求完成后回調(diào)的接口。
②接口實現(xiàn)類,即實現(xiàn)具體的Presenter類邏輯。
下面以代碼的形式一一展開。
①接口

public interface OnLoginFinishedListener {
    void onUsernameError();

    void onPasswordError();

    void onSuccess();
}

當(dāng)Model層得到請求的結(jié)果,需要回調(diào)Presenter層,讓Presenter層調(diào)用View層的接口方法。

public interface LoginPresenter {
    void validateCredentials(User user);

    void onDestroy();
}

登陸的Presenter 的接口,實現(xiàn)類為LoginPresenterImpl,完成登陸的驗證,以及銷毀當(dāng)前view。
②接口實現(xiàn)類

public class LoginPresenterImpl implements LoginPresenter, OnLoginFinishedListener {
    private LoginView loginView;
    private LoginModel loginModel;

    public LoginPresenterImpl(LoginView loginView) {
        this.loginView = loginView;
        this.loginModel = new LoginModelImpl();
    }

    @Override
    public void validateCredentials(User user) {
        if (loginView != null) {
            loginView.showProgress();
        }

        loginModel.login(user, this);
    }

    @Override
    public void onDestroy() {
        loginView = null;
    }

    @Override
    public void onUsernameError() {
        if (loginView != null) {
            loginView.setUsernameError();
            loginView.hideProgress();
        }
    }

    @Override
    public void onPasswordError() {
        if (loginView != null) {
            loginView.setPasswordError();
            loginView.hideProgress();
        }
    }

    @Override
    public void onSuccess() {
        if (loginView != null) {
            loginView.showSuccess();
        }
    }
}

由于presenter完成二者的交互,那么肯定需要二者的實現(xiàn)類(通過傳入?yún)?shù),或者new)。
presenter里面有個OnLoginFinishedListener, 其在Presenter層實現(xiàn),給Model層回調(diào),更改View層的狀態(tài), 確保 Model層不直接操作View層。

核心流程總結(jié)
View與Model并不直接交互,而是使用Presenter作為View與Model之間的橋梁。其中Presenter中同時持有View層的Interface的引用以及Model層的引用,而View層持有Presenter層引用。當(dāng)View層某個界面需要展示某些數(shù)據(jù)的時候,首先會調(diào)用Presenter層的引用,然后Presenter層會調(diào)用Model層請求數(shù)據(jù),當(dāng)Model層數(shù)據(jù)加載成功之后會調(diào)用Presenter層的回調(diào)方法通知Presenter層數(shù)據(jù)加載情況,最后Presenter層再調(diào)用View層的接口將加載后的數(shù)據(jù)展示給用戶。本例模式:

在這里插入圖片描述

一般模式:


在這里插入圖片描述
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • MVP模式已經(jīng)火了很長時間,似乎已經(jīng)火的過時。雖然現(xiàn)在MVVM風(fēng)頭正勁,但是MVP模式使用簡單方便,并使得耦合度降...
    Ruheng閱讀 14,448評論 3 47
  • 1 介紹 1.1 背景 ??MVP,全稱 Model-View-Presenter,要說MVP那就不得不說一說它的...
    Gs1993閱讀 1,763評論 0 4
  • 久違的晴天,家長會。 家長大會開好到教室時,離放學(xué)已經(jīng)沒多少時間了。班主任說已經(jīng)安排了三個家長分享經(jīng)驗。 放學(xué)鈴聲...
    飄雪兒5閱讀 7,787評論 16 22
  • 今天感恩節(jié)哎,感謝一直在我身邊的親朋好友。感恩相遇!感恩不離不棄。 中午開了第一次的黨會,身份的轉(zhuǎn)變要...
    余生動聽閱讀 10,798評論 0 11
  • 可愛進(jìn)取,孤獨成精。努力飛翔,天堂翱翔。戰(zhàn)爭美好,孤獨進(jìn)取。膽大飛翔,成就輝煌。努力進(jìn)取,遙望,和諧家園??蓯塾巫?..
    趙原野閱讀 3,443評論 1 1

友情鏈接更多精彩內(nèi)容