作者: 夏至 歡迎轉載托启,也請保留這份申明,謝謝尖殃。
1丈莺、什么是MVP
MVP,全稱 Model-View-Presenter分衫。它是從 MVC中演變過來的场刑,它的基本思想是相通的般此;在MVP中蚪战,View更加專注于處理數據的可視化以及用戶交互牵现,讓Model專注于數據的處理,而Presenter則邀桑,提供 View 與 Model 之間數據的紐帶瞎疼,用于交互與數據傳輸;如下面這張圖:
可以看到壁畸,在View 與 Model 之間我們是通過 Presenter贼急,也就是 interface 來實現view 與數據的交互的,大大降低耦合捏萍,方便進行單元測試太抓。至于與 MVC 的異同,自行google吧令杈,這里就不細說了走敌。
其實,自己在寫代碼的時候逗噩,心中有個概念就好了掉丽,view 就是UI,model就是數據處理异雁,而persenter 則是他們的紐帶捶障。心中有個輪廓,寫起來就不那么費勁了纲刀。
2项炼、使用 MVP 的 優(yōu)缺點
我們在使用一種設計模式的時候,首先都會問示绊,為什么要用這種模式芥挣,能給我們帶來哪些方便?用了這種模式耻台,它的缺點會不會給我的工程造成影響空免?
首先,優(yōu)點上盆耽,我們上面已經闡述了蹋砚;
- 減低耦合,實現了 Model 與View 的真正分離摄杂,修改 View 而不影響 Model
- 模塊職責分明坝咐,層次分明,便于維護析恢,多人開發(fā)首選墨坚。
- Presenter 可以服用,一個 Presenter可以用于多個 View映挂,不用去改 Presenter
- 利于單元測試泽篮。模塊分明盗尸,那么我們編寫單元測試就變得很方便了,而不用特別是特別搭平臺帽撑,人工模擬用戶操作等等耗時耗力的事情泼各。
缺點:
對于小工程,額外多出來的代碼量亏拉,和額外的代碼復雜度扣蜻,畢竟那么多 interface ,但對于它的有點來說及塘,完全可以接受莽使。
3、實戰(zhàn)
我們就簡單一個數據保存的例子好了笙僚。至于數據庫的保存吮旅,采用郭霖大神的 LitePal,連接如下:
http://blog.csdn.net/column/details/android-database-pro.html
先上效果:
非常簡單味咳,就是獲取 EditText的數據庇勃,保存在數據庫,然后重新把它讀取出來槽驶,結構圖如下:
首先责嚷,從上面的效果圖來看,我們需要 name 和 password 這兩個字符串掂铐,我們需要新建一個 User 類罕拂,由于要用到 LitePal ,所以讓它繼承 DataSupport全陨;如果你使用自己寫的爆班,那就不用繼承啥了。:
public class User extends DataSupport{
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
Model:
然后辱姨,我們思考一下柿菩,從View 傳過來的數據name和password,我們是要保存起來的雨涛,所以枢舶,我們先在 model,編寫數據保存和讀取的方法:
public interface IUserModel {
void saveUserData(User user);
User readUserData(String name);
}
它的具體實現方法如下:
/**
* Created by zhengshaorui on 2017/4/9.
*/
public class UserModel implements IUserModel {
public UserModel() {
}
/**
* 使用Litepal保存數據
* @return
*/
@Override
public void saveUserData(User user) {
user.save();
lg.d("user: "+user);
}
/**
* 通過 name從數據庫讀取數據
* @param name
* @return
*/
@Override
public User readUserData(String name) {
List<User> userList = DataSupport.where("username = ?",name).find(User.class);
if (userList.size() > 0)
return userList.get(0);
return null;
}
}
方法很簡單替久,就保存一下數據和讀數據凉泄。什么?數據庫保存這樣就行了蚯根?是的后众,所以趕緊去學習 LitePal 吧。
View:
View這里,我們是專注于UI的顯示和用戶交互的蒂誉,上面我們通過名字的方式從數據庫中讀取教藻,然后把它顯示出來。所以拗盒,我們需要添加 name 和password 的顯示方法,當然還有出錯的方法:
public interface IUserView {
void setUserName(String userName);
void setPassword(String password);
void error(String errormsg);
}
然后讓mainactivity 繼承這個接口重寫該方法:
@Override
public void setUserName(String userName) {
mUserEditText.setText(userName);
}
@Override
public void setPassword(String password) {
mPassEditText.setText(password);
}
@Override
public void error(String errormsg) {
Toast.makeText(this, errormsg, Toast.LENGTH_SHORT).show();
}
Presenter :
好了锥债,現在我們的 View 和 Model 都是單獨開了的陡蝇,所以,我們需要一個紐帶哮肚,把view 和model 連接起來登夫;那就是我們的 Presenter 了:
/**
* Created by zhengshaorui on 2017/4/9.
*/
public class UserPresenter {
private IUserView mIUserView;
private IUserModel mIUserModel;
public UserPresenter(IUserView mIUserView) {
this.mIUserView = mIUserView;
mIUserModel = new UserModel();
}
/**
* 數據保存
* @param user
*/
public void saveUser(User user){
mIUserModel.saveUserData(user);
}
/**
* 讀取數據
* @param name
*/
public void readUser(String name){
User user = mIUserModel.readUserData(name);
lg.d("getread: "+user);
if (user != null) {
mIUserView.setUserName(user.getUsername());
mIUserView.setPassword(user.getPassword());
}else{
mIUserView.error("沒有找到");
}
}
}
ok,其他都寫好了允趟,那么接下來恼策,只要寫onclick事件就可以了:
//保存
public void save(View view){
User user = new User();
user.setUsername(mUserEditText.getText().toString());
user.setPassword(mPassEditText.getText().toString());
mUserPresenter.saveUser(user);
}
//清空 edittext
public void clear(View view){
mUserEditText.setText("");
mPassEditText.setText("");
}
//讀數據
public void read(View view){
mUserPresenter.readUser(mReadEditText.getText().toString());
}
這樣,我們就實現了一個簡單的 MVP demo了潮剪。
疑問:
- 這樣涣楷,你可能會有疑問?一個簡單的demo被你寫得這么復雜抗碰,還說這個設計模式有多好狮斗?
- 這么簡單的,接口都那么多弧蝇,那稍微復雜點的碳褒,那接口不是直接上天和太陽肩并肩了嗎?
可能很多人有這樣的疑問看疗,是的沙峻,在一些小工程,或者一個項目只有一兩個人開發(fā)的時候两芳,你可以酌情考慮要不要使用這種模式摔寨,而使用這種模式,就考驗你對接口的理解和使用了怖辆。
而稍微復雜點的祷肯,和多人開發(fā)的,我建議是使用這種模式的疗隶,當然沒有完美的框架佑笋,適合自己的才是最重要的,反正我用的挺嗨的斑鼻,有點搞逼格的感覺蒋纬,筆者就試過一個稍微復雜的項目,多人開發(fā),最后搞得很混亂蜀备,牽一發(fā)而動全一身关摇;
當然也是見仁見智,最后附上demo的下載地址:https://github.com/LillteZheng/MvpDemo