概述
認識MVP模式
MVP 模式實際上指的是 Model-View-Presenter 主要的目的是為了劃分各個模塊的負責區(qū)域,分工明確,使代碼清晰了很多。也是為了減少 Activity 中代碼,使其沒有那么臃腫,提高測試性,主要的分工如下:
View 主要是負責顯示數(shù)據(jù)和與用戶進行交互,這可以是一個 Activity 或者是一個 Fragment,一個 android.view.View 或者是一個 Dialog。
Model 是數(shù)據(jù)源層,負責對數(shù)據(jù)進行存儲,檢索之類的操作。
Present 是 View 和 Model 進行交互的中間橋梁,負責 Model 和 View 兩者之間的處理,也就是說從Model中獲取的數(shù)據(jù)然后傳遞給 View,起到一個中間人的作用,也是在 MVP 模式中處理復雜邏輯的地方,后臺任務也是它負責的。
為什么要使用 MVP 模式?
使其盡可能的簡單
- 把復雜的任務分解成許多個簡單小任務來執(zhí)行
- 分解成的小任務 bug 比較少
- 減少測試時間
后臺任務不和 Activity 關聯(lián)
當你需要寫一個 Activity,F(xiàn)ragment 或者一個自定義 View 的時候,你可以將所有和后臺相關的方法放在一個外部類或者靜態(tài)類中,這樣你的后臺任務就不會和Activity有關聯(lián),也不存在內存的泄漏的問題。
MVP 模式說明
其實在 MVP 中 Activity 對應的就是 View,把 Activity 中的 UI 邏輯抽象成 View 接口,在 View 中進行 UI 設計和簡單的邏輯處理,Model 是業(yè)務邏輯和實體模型的實現(xiàn),Presenter 負責完成View于Model間的交互(在這里進行復雜的邏輯處理),圖片來自這里

由上圖可以看出,在 MVP 模式中 Model 和 View 是不能直接交互的,而是通過 Presenter這個中間橋梁進行交互, MVP 和 MVC 模式最大的區(qū)別就在于此。也可以看出View和Presenter是一對一的關系,Model 可以為不同的 Presenter 提供數(shù)據(jù)服務。一般來說 Presenter 與 View 的交互是通過接口來進行的,這樣有利于添加單元測試。
MVP 實例講解
說了那么多還是用一個 Demo 來說一下,這樣就比較好理解了。就用最簡單的例子來說吧,做的是一個登錄界面,輸入賬號和密碼,賬號密碼輸入正確的話則提示登錄成功,反之則登錄失敗。效果圖如下

項目結構

從項目結構可以直接看出來,首先必須是要有實體類,然后就是 Model 的接口和實例,里面便是業(yè)務類中的實現(xiàn)方法,還有就是 View 的接口和實例,里面是負責 UI 的繪制和用戶進行交互的邏輯,最后便是 Presenter,這里面作為 Model 和 View 的中間協(xié)調部分,負責兩者之間的業(yè)務邏輯處理,復雜的邏輯處理一般都在這里進行編寫。
實體類
首先是實體類的代碼,實體類是必須有的就不用多說了
package com.example.xiaozhang.userloginactivity;
/**
* Created by xiaozhang on 2016/11/3.
*/
//創(chuàng)建實體類,實體類必須有的?。?!
public class UserBean {
private String UserName;
private String PassWord;
public String getUserName() {
return UserName;
}
public void setUserName(String userName) {
UserName = userName;
}
public String getPassWord() {
return PassWord;
}
public void setPassWord(String passWord) {
PassWord = passWord;
}
}
Model
在 Model 中有一個業(yè)務的接口,處理邏輯交給 Presenter 就行了。
package com.example.xiaozhang.userloginactivity.Model;
import com.example.xiaozhang.userloginactivity.UserBean;
/**
* Created by xiaozhang on 2016/11/3.
*/
//Model接口------業(yè)務邏輯或者實體型接口
public interface IUserLoginModel {
void Login(UserBean mUserBean);
}
為了能讓點擊登錄后有提示,需要一個自定義 Listener 接口用來顯示在屏幕上作為提醒,代碼邏輯如下
package com.example.xiaozhang.userloginactivity.Model;
/**
* Created by xiaozhang on 2016/11/3.
*/
public interface IUserLoginListener {
void loginListener(boolean status);
}
最后是Model類中的業(yè)務類的邏輯編寫
package com.example.xiaozhang.loginactivity.Model;
import com.example.xiaozhang.loginactivity.UserBean;
/**
*
Created by xiaozhang on 2016/11/3.
*/
public class UserLoginModel implements IUserLoginModel {
private String UserName;
private String PassWord;
private IUserLoginListener LoginListener;
public UserLoginModel(IUserLoginListener loginListener){
this.LoginListener = loginListener;
}
@Override public void Login(UserBean mUserBean) {
boolean status = false;
UserName = mUserBean.getUserName();
PassWord = mUserBean.getPassWord();
if ("admin".equals(UserName)&&"123456".equals(PassWord))
status = true;
LoginListener.loginListener(status);
}
}
View
View 和 Presenter 交互是通過接口的行形式,不過在寫這個接口之前需要想一想需要實現(xiàn)的功能有哪些。
登錄功能上肯定要有用戶名和密碼
String getUserName();
String getPassWord();
重置功能上也是要有清除用戶名和密碼
void clearUserName();
void clearPassWord();
還有就是點擊登錄按鈕后顯示是否成功登錄的消息提示
void showMessage(String Message);
整合一下就是一個 View 接口的所有實現(xiàn)代碼了
package com.example.xiaozhang.userloginactivity.View;
/**
* Created by xiaozhang on 2016/11/3.
*/
public interface IUserLoginActivity {
String getUserName();
String getPassWord();
void clearUserName();
void clearPassWord();
void showMessage(String Message);
}
后面就是寫實現(xiàn)類了,前面說過了 Activity 對應的就是 View 的實現(xiàn)類,所以在 Activity中寫實現(xiàn)類的邏輯
package com.example.xiaozhang.userloginactivity.View;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;import android.widget.EditText;
import android.widget.Toast;
import com.example.xiaozhang.userloginactivity.Presenter.UserLoginPresenter;
import com.example.xiaozhang.userloginactivity.R;
public class UserLoginActivity extends AppCompatActivity implements IUserLoginActivity {
private EditText mInputUserName;
private EditText mInputPassWord;
private Button mLogin;
private Button mReset;
//這里需要注意下,沒有 Presenter 的話前面這些都白寫了,所以一定要創(chuàng)建實例!
private UserLoginPresenter mUserLoginPresenter = new UserLoginPresenter(this);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
mInputUserName = (EditText) findViewById(R.id.edit_input_Account);
mInputPassWord = (EditText) findViewById(R.id.edit_input_PassWord);
mLogin = (Button) findViewById(R.id.btn_Login);
mReset = (Button) findViewById(R.id.btn_Reset);
mLogin.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View view) {
//復雜的邏輯交給Presenter
mUserLoginPresenter.login();
}
});
mReset.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View view) {
//復雜的邏輯交給presenter
mUserLoginPresenter.Reset();
}
});
}
@Override public String getUserName() {
return mInputUserName.getText().toString();
}
@Override public String getPassWord() {
return mInputPassWord.getText().toString();
}
@Override public void clearUserName() {
mInputUserName.setText("");
}
@Override public void clearPassWord() {
mInputPassWord.setText("");
}
@Override public void showMessage(String Message) {
Toast.makeText(this, Message, Toast.LENGTH_LONG).show();
}
}
Presenter
前面也提到了 Presenter 是 View 和 Model 進行交互的中間橋梁,這也要看你在你的代碼里需要實現(xiàn)的是什么功能,在這里實現(xiàn)的登錄和重置功能的實現(xiàn)以及點擊登錄后是否能成功登錄出現(xiàn)的提示消息
package com.example.xiaozhang.userloginactivity.Presenter;
import com.example.xiaozhang.userloginactivity.Model.IUserLoginModel;
import com.example.xiaozhang.userloginactivity.Model.IUserLoginListener;
import com.example.xiaozhang.userloginactivity.Model.UserLoginModel;
import com.example.xiaozhang.userloginactivity.UserBean;
import com.example.xiaozhang.userloginactivity.View.IUserLoginActivity;
/**
* Created by xiaozhang on 2016/11/3.
*/
public class UserLoginPresenter implements IUserLoginListener{
private IUserLoginModel mIUserLoginModel;
private IUserLoginActivity mIUserLoginActivity;
public UserLoginPresenter(IUserLoginActivity mIULoginActivity) {
this.mIUserLoginActivity = mIULoginActivity; //這里命名后來發(fā)現(xiàn)不好區(qū)分,所以改了。。
mIUserLoginModel = new UserLoginModel(this);
}
public void login() {
UserBean mUserBean = new UserBean();
mUserBean.setUserName(mIUserLoginActivity.getUserName());
mUserBean.setPassWord(mIUserLoginActivity.getPassWord());
mIUserLoginModel.Login(mUserBean);
}
public void Reset() {
mIUserLoginActivity.clearPassWord();
mIUserLoginActivity.clearUserName();
}
@Override public void loginListener(boolean status) {
String Message;
if (status)
Message= "登錄成功";
else
Message= "登錄失敗,請檢查賬號密碼是否正確";
mIUserLoginActivity.showMessage(Message); }
}
總結
以上便是我對MVP的初步認識,畢竟自己也是剛接觸這個不久,所以寫的不好還請指導。對于剛接觸到MVP模式還是有很多的問題,只能參考寫出這么一個簡單的Demo,后面也會從接觸到的項目中學習到MVP的用法,到時候也會寫出來和大家分享。