概述
首先我們應該是知道的是,軟件設計中,降低耦合度是很重要的,大名鼎鼎的MVC(Model-View-Controller)便是因此而生,而在android設計中MVP早就紅了半邊天,我也在簡書博客中看到一些文章 前端也在談這一套軟件設計模式,雖然如今大勢已經是MVVM,但是腳步得一扎一個穩, 我們先學習MVP是很有必要的。
MVP(Model-View-Presenter,模型-視圖-表示器)模式則是由IBM開發出來的一個針對C++和Java的編程模型,大概出現于2000年,是MVC模式的一個變種,主要用來隔離UI、UI邏輯和業務邏輯、數據。也就是說,MVP 是從經典的模式MVC演變而來,它們的基本思想有相通的地方:Controller/Presenter負責邏輯的處理,Model提供數據,View負責顯示。
View層不再和Model層關聯,他們之間通過Presenter層關聯,這里就出明顯的感覺出P層的任務會比較重,邏輯會相對其他層復雜,同時也是MVP中最關鍵的層。而聯系M-P,P-V的紐帶,是接口,即本質是面向接口的編程,來降低各個模塊的耦合度,其實與Presenter相關的兩個接口ViewInterface、ModelInterface,View其實是ViewInterface的實現類,Model是ModelInterface實現類,然后通過接口Presenter便輕松的連接了Model與View(這只是最簡單的模型情況,事實上,Model與Presenter并不是簡單直接定義的類,實現時,有是繼承抽象類的,有繼承基礎的泛型類的,有實現某些接口的,我們在這里只編寫簡單的模型即可)
谷歌官方也有MVPdemo todo_mvp,其將接口以內部類的形式封裝在一個總的接口類里,且我覺得其實現方法沒有鴻洋大神寫的好,同時送上鴻洋的MVP blog 鴻洋 MVP
同時,對于RxJava的MVP,則是另一套,以后學到時我會再整理一篇。
編寫
我們編寫一個簡單的demo,功能為每次開啟應用時顯示存儲在本地的名字,同時有一個按鈕,編輯名字后按該按鈕保存名字,下次啟動后便為上次的名字:
首先看目錄
編寫model
首先我們要知道model需要進行什么操作,我們需要進行名字的存儲和讀取操作,因此定義了如下接口
package com.example.mvpdemo.datamodel;
/**
* Created by Xiamin on 2016/9/5.
*/
public interface IGetString {
public String getName();
public void saveName(String name);
}
我們編寫該接口的實現類,即我們的model具體實現
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有一個EditText,一個Button,我們需要進行EditText的數據讀取和填充操作,因此我們定義了如下接口
package com.example.mvpdemo.view;
/**
* Created by Xiamin on 2016/9/5.
*/
public interface IGetStringView {
public void showName(String name);
public String getName();
}
view的實現類為
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編寫就很簡單了,多態獲取兩個接口的實現類,并進行相應操作
/**
* 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());
}
}
總結
這樣我們一個簡單的mvp的demo便能運行起來了,通過閱讀代碼我們發現,view中未作任何數據操作,只負責與UI的交互,而Preneter中的操作也變得很簡單,因為之前接口的定義恰當, 我們僅僅是通過
getString.saveName(getStringView.getName());簡單的一句話就獲取 了數據并存儲到了本地。
希望大家都編寫自己的demo,編寫完做一些功能的修改,便會發現解耦帶來的莫大好處。希望通過跟著本文章的編寫,能給大家帶來更多的思考。
ps:新人一枚,請多多指教