一、爲什麼使用MVP?
1. MVC傳統模式架構的劣勢
M層:數據層->包含(數據庫、文件、網絡、Javabean等等…)
V層:UI層->包含(View以及子類、Fragment以及子類、Activity以及子類)
C層:中介->作用(目的:就是將UI層和數據層進行解耦和,同時進行關聯)
我們在安卓中使用最多的就是MVC,相對來說他要求的技術難點較低,好寫,尤其是view層和control,安卓自身就已經做了一定的拆分。
缺點:
視圖層(V層)和 邏輯層(C層)依然拆分不徹底,耦合性還是高,不利於維護、閱讀、迭代。
使用MVC的框架列舉:
Android基於MVC的設計模式 , 百度地圖基於MVC的架構 等
Android基於MVC的設計模式:
View層:xml ,
C 層:Actvity ,
M層:一個類中。
關於MVC各層之間關係所對應的設計模式
View層,單獨實現了組合模式
Model層和View層,實現了觀察者模式
View層和Controller層,實現了策咯模式
2. 中介者設計模式
其實大家會發現這個統計部門很類似於中介 ,統計部門使得這些對象不必相互明顯作用。從而使它們可以降低耦合(鬆散耦合)。
當某些對象之間的作用發生改變時,不會立即影響其他的一些對象之間的作用。保證這些作用可以彼此獨立變化。中介者模式將多對多的相互作用轉化爲一對多的相互作用。中介者模式將對象的行爲和協作抽象化,把對象在小尺度的行爲上與其他對象的相互作用分開處理。
簡單來說 : 用一箇中介對象來封裝一系列的對象交互。中介者使各對象不需要顯式地相互引用,從而使其耦合鬆散,而且可以獨立地改變它們之間的交互。
中介者模式-應用場景?
.
當對象之間的交互操作很多且每個對象的行爲操作都依賴彼此時,爲防止在修改一個對象的行爲時,同時涉及修改很多其他對象的行爲,可以採用中介者模式來解決緊耦合問題。
.如果還是對於中介者模式不瞭解,可以下載下面的代碼看一下
中介者模式代碼 Demo下載
3. MVP中模塊拆分化思想的優勢
Model:數據層. 負責與網絡層和數據庫層的邏輯交互.
View :UI層. 顯示數據, 並向Presenter報告用戶行爲.
Presenter:從Model拿數據, 應用到UI層, 管理UI的狀態, 決定要顯示什麼, 響應用戶的行爲.
M層:數據層 --> 包含(數據庫、文件、網絡、Javabean等等…)
V層:UI層 --> 包含(View以及子類、Fragment以及子類、Activity以及子類)
P層:中介 --> 作用(目的:就是將UI層和數據層進行解耦和,同時進行關聯)
MVP設計目的:爲了將UI層和數據層進行分離
MVP模式的最主要優勢就是耦合降低, Presenter變爲純Java的代碼邏輯, 不再與Android Framework中的類,如Activity, Fragment等關聯, 便於寫單元測試。
二、MVP的使用
1. MVP角色劃分
抽象層
- M層 ===》MvpModel
- V層 ===》LoginView(UI交互接口)
- P層 ===》MvpPresenter
具體實現層
- M層 ===》LoginModel
- V層 ===》MainActivity(或者:Fragment)
- P層 ===》LoginPresenter
2. MVP代碼案例
抽象層
- M層 ===》MvpModel
public abstract class MvpModel{
}
- V層 ===》LoginView(UI交互接口)
public interface LoginView{
void onLoginResult(String reslt);
}
- P層 ===》MvpPresenter
public abstract class MvpPresenter{
private LoginModel model;
private LoginView view;
public LoginView getView(){
return view;
}
//V層綁定的方法
public void attachView(LoginView view){
this.view = view;
}
//V層解綁的方法
public void detchView(){
this.view=null;
}
}
具體實現層
- M層 ===》LoginModel
public class LoginModel extends MvpModel{
public void login(String username,String password,
final HttpUtils.OnHttpResultListener listener){
Map<String,Object> params = new HashMap<>();
params.put("phone",username);
params.put("pwd",password);
new HttpTask.Builder()
.method("POST")
.url("http://172.17.8.100/small/user/v1/login")
.paramMap(params)
.onHttpResultListener(new HttpUtils.OnHttpResultListener(){
@Override
public void onResult(String result){
listener.onResult(result);
}
}).build().execute();
}
}
- P層 ===》LoginPresenter
public class LoginPresenter extends MvpPresenter{
private LoginModel model;
public LoginPresenter(){
this.model = new LoginModel();
}
public void login(String username,String password){
this.model.login(username,password,
new HttpUtils.OnHttpResultListener(){
@Override
public void onResult(String result){
if(getView()!=null){
getView().onLoginResult(result);
}
}
});
}
}
- V層 ===》MainActivity(或者:Fragment)
public class MainActivity extends AppCompatActivity
implements LoginView{
private LoginPresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.presenter = new LoginPresenter();
//綁定View
this.presenter.attachView(this);
}
public void clickLogin(View view){
this.presenter.login("15001194794","123");
}
@Override
public void onLoginResult(String reslt){
Toast.makeText(MainActivity.this,reslt,
Toast.LENGTH_LONG).show();
}
@Override
protected void onDestroy(){
super.onDestroy();
presenter.detchView();
}
}
三、MVP複雜案例
1. 複雜MVP角色劃分
接口層
- M層 ===》MvpModel
- V層 ===》MvpView
- P層 ===》MvpPresenter
抽象層
- M層 ===》BaseModel
- V層 ===》BaseActivity
- P層 ===》BasePresenter
具體實現層
- M層 ===》LoginModel
- V層 ===》LoginView、MainActivity(或者:Fragment)
- P層 ===》LoginPresenter
2. 複雜MVP代碼案例
(1)接口層
- M層 ===》MvpModel
public interface MvpModel {
}
- V層 ===》MvpView
public interface MvpView {
}
- P層 ===》MvpPresenter
public interface MvpPresenter <V extends MvpView>{
//關聯視圖
void attachView(V view);
//分離視圖
void detachView();
}
(2)抽象層
- M層 ===》BaseModel
public abstract class BaseModel implements MvpModel {
private Context context;
public BaseModel(Context context) {
this.context = context;
}
public Context getContext() {
return context;
}
}
- V層 ===》BaseActivity
public abstract class BaseActivity<V extends MvpView,
P extends MvpPresenter<V>> extends AppCompatActivity
implements MvpView {
private P presenter;
public abstract P createPersenter();
public P getPresenter() {
return presenter;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (presenter == null) {
this.presenter = createPersenter();
}
if (presenter != null) {
//關聯視圖
this.presenter.attachView((V) this);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
//分離視圖
this.presenter.detachView();
}
}
- P層 ===》BasePresenter
public class BasePresenter <V extends MvpView> implements MvpPresenter<V> {
private V view;
public V getView(){
return view;
}
@Override
public void attachView(V view){
this.view = view;
}
@Override
public void detachView(){
this.view = null;
}
}
(3)具體實現層
- M層 ===》LoginModel
public class LoginModel extends BaseModel {
public LoginModel(Context context) {
super(context);
}
public void httpLogin(String username, String password,
final HttpUtils.OnHttpResultListener listener) {
//僞登錄
if (username.equals("12345")&&password.equals("000")){
listener.onResult("登錄成功");
return;
}
// 本地接口
// Map<String, Object> params = new HashMap<>();
// params.put("phone", username);
// params.put("pwd", password);
//
// new HttpTask.Builder()
// .method("POST")
// .url("http://172.17.8.100/small/user/v1/login")
// .paramMap(params)
// .onHttpResultListener(new HttpUtils.OnHttpResultListener() {
//
// @Override
// public void onResult(Object result) {
// listener.onResult(result);
// }
// }).build().execute();
}
}
- P層 ===》LoginPresenter
public class LoginPresenter extends BasePresenter<LoginView> {
private LoginModel model;
public LoginPresenter(Context mContext) {
this.model = new LoginModel(mContext);
}
public void login(String username, String password) {
this.model.httpLogin(username, password,
new HttpUtils.OnHttpResultListener() {
@Override
public void onResult(Object result) {
getView().onLogin((String) result);
}
});
}
}
- V層 ===》LoginView、MainActivity(或者:Fragment)
LoginView.java
public interface LoginView extends MvpView {
void onLogin(String result);
}
MainActivity.java
public class MainActivity extends BaseActivity<LoginView, LoginPresenter>
implements LoginView {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
getPresenter().login("12345", "000");
}
});
}
@Override
public void onLogin(String result) {
Toast.makeText(this, "返回內容:" + result, Toast.LENGTH_LONG).show();
}
@Override
public LoginPresenter createPersenter() {
return new LoginPresenter(this);
}
}