概述
首先我們應(yīng)該是知道的是,軟件設(shè)計(jì)中,降低耦合度是很重要的,大名鼎鼎的MVC(Model-View-Controller)便是因此而生,而在android設(shè)計(jì)中MVP早就紅了半邊天,我也在簡書博客中看到一些文章 前端也在談這一套軟件設(shè)計(jì)模式,雖然如今大勢已經(jīng)是MVVM,但是腳步得一扎一個(gè)穩(wěn), 我們先學(xué)習(xí)MVP是很有必要的。
MVP(Model-View-Presenter,模型-視圖-表示器)模式則是由IBM開發(fā)出來的一個(gè)針對C++和Java的編程模型,大概出現(xiàn)于2000年,是MVC模式的一個(gè)變種,主要用來隔離UI、UI邏輯和業(yè)務(wù)邏輯、數(shù)據(jù)。也就是說,MVP 是從經(jīng)典的模式MVC演變而來,它們的基本思想有相通的地方:Controller/Presenter負(fù)責(zé)邏輯的處理,Model提供數(shù)據(jù),View負(fù)責(zé)顯示。

View層不再和Model層關(guān)聯(lián),他們之間通過Presenter層關(guān)聯(lián),這里就出明顯的感覺出P層的任務(wù)會(huì)比較重,邏輯會(huì)相對其他層復(fù)雜,同時(shí)也是MVP中最關(guān)鍵的層。而聯(lián)系M-P,P-V的紐帶,是接口,即本質(zhì)是面向接口的編程,來降低各個(gè)模塊的耦合度,其實(shí)與Presenter相關(guān)的兩個(gè)接口ViewInterface、ModelInterface,View其實(shí)是ViewInterface的實(shí)現(xiàn)類,Model是ModelInterface實(shí)現(xiàn)類,然后通過接口Presenter便輕松的連接了Model與View(這只是最簡單的模型情況,事實(shí)上,Model與Presenter并不是簡單直接定義的類,實(shí)現(xiàn)時(shí),有是繼承抽象類的,有繼承基礎(chǔ)的泛型類的,有實(shí)現(xiàn)某些接口的,我們在這里只編寫簡單的模型即可)
谷歌官方也有MVPdemo todo_mvp,其將接口以內(nèi)部類的形式封裝在一個(gè)總的接口類里,且我覺得其實(shí)現(xiàn)方法沒有鴻洋大神寫的好,同時(shí)送上鴻洋的MVP blog 鴻洋 MVP
同時(shí),對于RxJava的MVP,則是另一套,以后學(xué)到時(shí)我會(huì)再整理一篇。
編寫
我們編寫一個(gè)簡單的demo,功能為每次開啟應(yīng)用時(shí)顯示存儲(chǔ)在本地的名字,同時(shí)有一個(gè)按鈕,編輯名字后按該按鈕保存名字,下次啟動(dòng)后便為上次的名字:
首先看目錄

編寫model
首先我們要知道m(xù)odel需要進(jìn)行什么操作,我們需要進(jìn)行名字的存儲(chǔ)和讀取操作,因此定義了如下接口
package com.example.mvpdemo.datamodel;
/**
* Created by Xiamin on 2016/9/5.
*/
public interface IGetString {
public String getName();
public void saveName(String name);
}
我們編寫該接口的實(shí)現(xiàn)類,即我們的model具體實(shí)現(xiàn)
package com.example.mvpdemo.datamodel;
import android.content.Context;
import android.content.SharedPreferences;
import com.example.mvpdemo.MainActivity;
/**
* Created by Xiamin on 2016/9/5.
*/
public class FileOperate implements IGetString {
@Override
public String getName() {
String name;
SharedPreferences sharedPreferences;
sharedPreferences = MainActivity.getAppContext().getSharedPreferences("data", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
name = sharedPreferences.getString("name","");
return name;
}
@Override
public void saveName(String name) {
SharedPreferences sharedPreferences;
sharedPreferences = MainActivity.getAppContext().getSharedPreferences("data", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("name",name);
editor.commit();
}
}
編寫view
我們的view有一個(gè)EditText,一個(gè)Button,我們需要進(jìn)行EditText的數(shù)據(jù)讀取和填充操作,因此我們定義了如下接口
package com.example.mvpdemo.view;
/**
* Created by Xiamin on 2016/9/5.
*/
public interface IGetStringView {
public void showName(String name);
public String getName();
}
view的實(shí)現(xiàn)類為
public class MainActivity extends AppCompatActivity implements IGetStringView{
private EditText editText;
private Button button;
private GetStringPresenter presenter;
private static Context mContext ;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText) findViewById(R.id.editText);
button = (Button) findViewById(R.id.button);
mContext = getApplicationContext();
presenter = new GetStringPresenter(this);
presenter.showName();
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
presenter.saveName();
}
});
}
@Override
public void showName(String name) {
editText.setText(name);
}
@Override
public String getName() {
return editText.getText().toString();
}
public static Context getAppContext()
{
return mContext;
}
}
編寫presenter
Presenter編寫就很簡單了,多態(tài)獲取兩個(gè)接口的實(shí)現(xiàn)類,并進(jìn)行相應(yīng)操作
/**
* Created by Xiamin on 2016/9/5.
*/
public class GetStringPresenter {
private IGetString getString;
private IGetStringView getStringView;
public GetStringPresenter(IGetStringView view)
{
this.getStringView = view;
getString = new FileOperate();
}
public void saveName()
{
getString.saveName(getStringView.getName());
}
public void showName()
{
getStringView.showName(getString.getName());
}
}
總結(jié)
這樣我們一個(gè)簡單的mvp的demo便能運(yùn)行起來了,通過閱讀代碼我們發(fā)現(xiàn),view中未作任何數(shù)據(jù)操作,只負(fù)責(zé)與UI的交互,而Preneter中的操作也變得很簡單,因?yàn)橹敖涌诘亩x恰當(dāng), 我們僅僅是通過
getString.saveName(getStringView.getName());簡單的一句話就獲取 了數(shù)據(jù)并存儲(chǔ)到了本地。
希望大家都編寫自己的demo,編寫完做一些功能的修改,便會(huì)發(fā)現(xiàn)解耦帶來的莫大好處。希望通過跟著本文章的編寫,能給大家?guī)砀嗟乃伎肌?/p>
ps:新人一枚,請多多指教