MVP簡介
相信大家對 MVC 都是比較熟悉了:M-Model-模型、V-View-視圖冈在、C-Controller-控制器械荷,MVP作為MVC的演化版本,也是作為用戶界面(用戶層)的實現(xiàn)模式谆沃,那么類似的MVP所對應(yīng)的意義:M-Model-模型、V-View-視圖仪芒、P-Presenter-表示器唁影。從MVC和MVP兩者結(jié)合來看,Controlller/Presenter在MVC/MVP中都起著邏輯控制處理的角色桌硫,起著控制各業(yè)務(wù)流程的作用夭咬。而MVP與MVC最不同的一點是M與V是不直接關(guān)聯(lián)的也是就Model與View不存在直接關(guān)系,這兩者之間間隔著的是Presenter層铆隘,其負責(zé)調(diào)控View與Model之間的間接交互卓舵,MVP的結(jié)構(gòu)圖如下所示,對于這個圖理解即可而不必限于其中的條條框框膀钠,畢竟在不同的場景下多少會有些出入的掏湾。在Android中很重要的一點就是對UI的操作基本上需要異步進行也就是在MainThread中才能操作UI,所以對View與Model的切斷分離是合理的肿嘲。此外Presenter與View融击、Model的交互使用接口定義交互操作可以進一步達到松耦合也可以通過接口更加方便地進行單元測試。
MVP之Model
Model 是用戶界面需要顯示數(shù)據(jù)的抽象雳窟,也可以理解為從業(yè)務(wù)數(shù)據(jù)(結(jié)果)那里到用戶界面的抽象(Business rule, data access, model classes)尊浪。本文 Demo 為了簡單處理就直接把業(yè)務(wù)放到了對應(yīng)的 Model 之中匣屡。
MVP之View
視圖這一層體現(xiàn)的很輕薄,負責(zé)顯示數(shù)據(jù)拇涤、提供友好界面跟用戶交互就行捣作。MVP下Activity和Fragment體現(xiàn)在了這一層,Activity一般也就做加載UI視圖鹅士、設(shè)置監(jiān)聽再交由Presenter處理的一些工作券躁,所以也就需要持有相應(yīng)Presenter的引用。例如掉盅,Activity上滾動列表時隱藏或者顯示Acionbar(Toolbar)也拜,這樣的UI邏輯時也應(yīng)該在這一層。另外在View上輸入的數(shù)據(jù)做一些判斷時趾痘,例如慢哈,EditText的輸入數(shù)據(jù),假如是簡單的非空判斷則可以作為View層的邏輯扼脐,而當(dāng)需要對EditText的數(shù)據(jù)進行更復(fù)雜的比較時岸军,如從數(shù)據(jù)庫獲取本地數(shù)據(jù)進行判斷時明顯需要經(jīng)過Model層才能返回了,所以這些細節(jié)需要自己掂量瓦侮。
MVP之Presenter
MVP之Presenter
Presenter這一層處理著程序各種邏輯的分發(fā),收到View層UI上的反饋命令佣谐、定時命令肚吏、系統(tǒng)命令等指令后分發(fā)處理邏輯交由業(yè)務(wù)層做具體的業(yè)務(wù)操作,然后將得到的 Model 給 View 顯示
小結(jié)
綜上MVP小結(jié)如下:
- View 對應(yīng)于Activity狭魂,負責(zé)View的繪制以及與用戶交互
- Model 依然是業(yè)務(wù)邏輯和實體模型
- Presenter 負責(zé)完成View于Model間的交互
視圖如下:
項目展示
框架:
界面視圖:
圖中明顯的三層:Model包罚攀、Presenter包、UI包雌澄,其中斋泄,三者都實現(xiàn)各自的結(jié)構(gòu),Model為UserModel镐牺、Presenter為UserPresenter炫掐、View為UserActivity;其中每個接口都有具體實現(xiàn)類睬涧。
數(shù)據(jù)Model
首先我們需要一個Note 募胃,用來保存用戶信息
public class Note {
private Long id;
/** Not-null value. */
private String text;
private String comment;
private java.util.Date date;
public Note() {
}
public Note(Long id) {
this.id = id;
}
public Note(Long id, String text, String comment, java.util.Date date) {
this.id = id;
this.text = text;
this.comment = comment;
this.date = date;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
/** Not-null value. */
public String getText() {
return text;
}
/** Not-null value; ensure this value is available before it is saved to the database. */
public void setText(String text) {
this.text = text;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public java.util.Date getDate() {
return date;
}
public void setDate(java.util.Date date) {
this.date = date;
}
}
定義Model相關(guān)接口IDataModel,以UserModel實現(xiàn)畦浓,用來為Presenter 層調(diào)用痹束。
public interface IDataModel {
void setUserName (String userName);
void setComment (String comment);
Note load (String userName);
}
public class UserModel implements IDataModel{
private String mUserName;
private String mComment;
@Override
public void setUserName(String userName) {
mUserName=userName;
}
@Override
public void setComment(String comment) {
mComment=comment;
Note note=new Note();
note.setText(mUserName);
note.setComment(comment);
DBManager.getInstance().getNoteDao().insert(note);
}
@Override
public Note load(String userName) {
Note note=DBManager.getInstance().getNote(userName);
return note;
}
}
View層
基于項目需要展示用戶、評論讶请,并由GreenDao 數(shù)據(jù)庫讀寫祷嘶,定義以下接口:
public interface IUserView {
String getUserName();
String getComment();
void setUserName(String userName);
void setComment(String comment);
}
Activity持有Presenter對象,便于操作數(shù)據(jù)及UI。
public class UserActivity extends Activity implements View.OnClickListener,IUserView{
private EditText mUserName , mComment ;
private Button mSaveButton , mLoadButton ;
private UserPresenter userPresenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_querydb_main);
findWidgets();
userPresenter=new UserPresenter(this);
}
void findWidgets() {
mUserName = (EditText) findViewById(R.id.first_name_edt);
mComment = (EditText) findViewById(R.id.last_name_edt);
mSaveButton = (Button) findViewById(R.id.saveButton);
mLoadButton = (Button) findViewById(R.id.loadButton);
mSaveButton.setOnClickListener(this);
mLoadButton.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.saveButton:
userPresenter.saveUser(getUserName(),getComment());
break;
case R.id.loadButton:
userPresenter.loadUser(getUserName());
break;
}
}
@Override
public String getUserName() {
return mUserName.getText().toString();
}
@Override
public String getComment() {
return mComment.getText().toString();
}
@Override
public void setUserName(String userName) {
mUserName.setText(userName);
}
@Override
public void setComment(String comment) {
mComment.setText(comment);
}
}
Presenter層
同時持有View、Model層接口论巍,并提供saveUser剿牺,loadUser接口,提供View_Model數(shù)據(jù)傳遞及展示UI的橋梁环壤。
public interface IUserPresenter {
void saveUser(String userName,String comment);
void loadUser(String userName);
}
public class UserPresenter implements IUserPresenter{
private IUserView iUserView;
private IDataModel iDataModel;
public UserPresenter(IUserView iUserView){
this.iUserView=iUserView;
this.iDataModel=new UserModel();
}
@Override
public void saveUser(String userName, String comment) {
iDataModel.setUserName(userName);
iDataModel.setComment(comment);
}
@Override
public void loadUser(String userName) {
Note note=iDataModel.load(userName);
iUserView.setUserName(note.getText());
iUserView.setComment(note.getComment());
}
}
希望能助你解惑
Git項目源碼