31.Android MVP模式
Android MVP介紹
先說說MVC吧,MVC(Model-View-Controller)是Java中一種非常常用的開發模式。但是在Android中,View的話可以很容易想到Activity和Fragment,但是Controller的話,我們怎麼想都還是Activity,因爲無論是Activity還是Fragment跳轉的話,都要執行startActivity
,所以無論怎麼想,Controller都是由Activity在兼職。。
Activity身兼View和Controller的職位,導致代碼過度耦合,上千行也是常有的。
MVP(Model-View-Presenter)MVP的主要思想:
Activity或Fragment的UI邏輯對象抽象成View Interface,業務邏輯抽象成Presenter Interface,M不變。
Activity上只做簡單回調接口的數據渲染,組件的簡單操作。剩下的耗時工作(網絡請求)都交給Presenter去執行。Presenter是Model和View的橋樑,Presenter處理網絡請求後拿到的數據實例化Model,然後再將Model通過View Interface回調給View。
MVC 和 MVP 的區別: MVP中的View不能對Model直接操作。
Android MVP UML圖
Android MVP實現
實體類 - Topic
public class Topic {
/**
* 用戶Id
*/
public Long userId;
/**
* 主題Id
*/
public Long topicId;
/**
* 主題內容
*/
public String content;
}
Presenter層回調View層接口 - IMvpView
public interface IMvpView {
/**
* 添加成功
* @param topic
*/
void addSuccess(Topic topic);
/**
* 刪除成功
* @param topic
*/
void delSuccess(Topic topic);
/**
* 修改成功
* @param newTopic
*/
void modSuccess(Topic newTopic);
/**
* 查詢成功
* @return
*/
void querySuccess(List<Topic> topics);
/**
* 發生錯誤
*/
void error();
}
Model層 接口 - ITopicModel
public interface ITopicModel {
/**
* 添加Topic
*
* @param topic
*/
void add(Topic topic);
/**
* 刪除主題
*
* @param topic
*/
void del(Topic topic);
/**
* 修改主題
*
* @param topicId
* @param topic
*/
void mod(Long topicId, Topic topic);
/**
* 查詢主題
*
* @return
*/
void query();
}
Model層回調Presenter層抽象類 - TopicModelCallBack
public abstract class TopicModelCallBack {
/**
* 添加成功
*
* @param topic
*/
public void addSuccess(Topic topic) {
}
/**
* 刪除成功
*
* @param topic
*/
public void delSuccess(Topic topic) {
}
/**
* 修改成功
*
* @param newTopic
*/
public void modSuccess(Topic newTopic) {
}
/**
* 查詢成功
*
* @return
*/
public void querySuccess(List<Topic> topics) {
}
/**
* 發生錯誤
*/
public abstract void error();
}
Model 實現類 - TopicModel
public class TopicModel implements ITopicModel {
private TopicModelCallBack callBack;
public TopicModel(TopicModelCallBack callBack) {
this.callBack = callBack;
}
/**
* 添加Topic
*
* @param topic
*/
@Override
public void add(Topic topic) {
// TODO ...網絡請求後...
// TODO 返回數據 這裏默認爲返回原數據
this.callBack.addSuccess(topic);
}
/**
* 刪除主題
*
* @param topic
*/
@Override
public void del(Topic topic) {
// TODO ...網絡請求後...
// TODO 返回數據 這裏默認爲返回原數據
this.callBack.delSuccess(topic);
}
/**
* 修改主題
*
* @param topicId
* @param topic
*/
@Override
public void mod(Long topicId, Topic topic) {
// TODO ...網絡請求後...
// TODO 返回數據 這裏默認爲返回原數據
this.callBack.modSuccess(topic);
}
/**
* 查詢主題
*
* @return
*/
@Override
public void query() {
// TODO ...網絡請求後...
// TODO 返回數據
Topic topic = new Topic();
topic.userId = 267L;
topic.topicId = 1267L;
topic.content = "Save you from anything";
List<Topic> list = new LinkedList<Topic>();
list.add(topic);
this.callBack.querySuccess(list);
}
}
Presenter層 - MvpPresenter
public class MvpPresenter {
private IMvpView iView;
private ITopicModel model;
public MvpPresenter(IMvpView iView) {
this.iView = iView;
this.model = new TopicModel(new TopicModelCallBack() {
/**
* 添加成功
*
* @param topic
*/
@Override
public void addSuccess(Topic topic) {
MvpPresenter.this.iView.addSuccess(topic);
}
/**
* 刪除成功
*
* @param topic
*/
@Override
public void delSuccess(Topic topic) {
MvpPresenter.this.iView.delSuccess(topic);
}
/**
* 修改成功
*
* @param newTopic
*/
@Override
public void modSuccess(Topic newTopic) {
MvpPresenter.this.iView.modSuccess(newTopic);
}
/**
* 查詢成功
*
* @param topics
* @return
*/
@Override
public void querySuccess(List<Topic> topics) {
MvpPresenter.this.iView.querySuccess(topics);
}
/**
* 發生錯誤
*/
@Override
public void error() {
MvpPresenter.this.iView.error();
}
});
}
/**
* 添加主題
*
* @param topic
*/
public void addTopic(Topic topic) {
this.model.add(topic);
}
/**
* 刪除主題
*
* @param topic
*/
public void delTopic(Topic topic) {
this.model.del(topic);
}
/**
* 修改主題
*
* @param topic
*/
public void modTopic(Topic topic) {
this.model.mod(topic.topicId, topic);
}
/**
* 查詢主題
*/
public void queryTopic() {
this.model.query();
}
}
Activity
public class MvpActivity extends AppCompatActivity implements IMvpView {
private TextView addTV;
private TextView delTV;
private TextView modTV;
private TextView queryTV;
private MvpPresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mvp);
this.addTV = (TextView) this.findViewById(R.id.add_tv);
this.delTV = (TextView) this.findViewById(R.id.del_tv);
this.modTV = (TextView) this.findViewById(R.id.mod_tv);
this.queryTV = (TextView) this.findViewById(R.id.query_tv);
this.presenter = new MvpPresenter(this);
Topic topic = new Topic();
topic.userId = 267L;
topic.topicId = 1267L;
topic.content = "Save you from anything";
this.presenter.addTopic(topic);
this.presenter.delTopic(topic);
this.presenter.modTopic(topic);
this.presenter.queryTopic();
}
/**
* 添加成功
*
* @param topic
*/
@Override
public void addSuccess(Topic topic) {
Log.i("MvpActivity", topic.content);
this.addTV.setText("Add:"+topic.content);
}
/**
* 刪除成功
*
* @param topic
*/
@Override
public void delSuccess(Topic topic) {
Log.i("MvpActivity",topic.content);
this.delTV.setText("Del:"+topic.content);
}
/**
* 修改成功
*
* @param newTopic
*/
@Override
public void modSuccess(Topic newTopic) {
Log.i("MvpActivity", newTopic.content);
this.modTV.setText("Mod:" + newTopic.content);
}
/**
* 發生錯誤
*/
@Override
public void error() {
}
/**
* 查詢成功
*
* @param list
* @return
*/
@Override
public void querySuccess(List<Topic> list) {
Topic topic = list.get(0);
Log.i("MvpActivity",topic.content);
this.queryTV.setText("Query:"+topic.content);
}
}
Android MVP項目結構
Android MVP作用
在Android上,分離了View和Controller,大大降低了耦合度。
Activity只處理簡單的事情,代碼乾淨。
Presenter被抽象出來可以有多種具體的實現,方便進行單元測試。
Presenter和View都獨立出來了,不互相耦合,提升了各自功能的特點和可讀性(比如Presenter就是幹這個的,View是幹這個的,很容易看出來)。
網絡的耗時任務內,可能Activity的引用還被耗時任務引用着,這樣會造成內存泄露,如果業務邏輯交給Presenter,可以在onDestory的時候讓Presenter分離耗時任務和Activity的引用。