一、什麼是MVP?
MVP是基於MVC提出來的,MVC模式在android開發中的體現不是特別的明顯,尤其是當我們按照傳統的寫法,會在Activity和Fragment中寫大量的業務邏輯和UI界面操作的代碼,以至於Controller和View分隔的不是特別的明顯。然而MVP的出現完美的解決了Activity/Fragment中業務邏輯和界面操作的耦合問題。簡而言之,MVP的出現就是爲了解耦,提高代碼可維護性。
MVP中:Presenter在這裏充當了MVC中Controller的角色,Model只能通過Presenter來通知View進行界面的更新。代碼結構如下圖所示:
Data Layer:非傳統意義的 Model 層,包含 dto(Data Transfer Object)、service 和 model。其中 service 包含 Net和 Local 等不同服務,用於提供不同的數據服務。model 負責處理某個業務對象的業務邏輯,並通過 dto 或元數據 與 Presenter 層進行交互。
View Layer:視圖層,包括各種activity,adapter,fragment,view。只關注與用戶交互,以及視圖操作(動畫、界面輸出、更新等)。
Presenter Layer:控制邏輯層。將控制邏輯從 Activity 中剝離並抽象成不同的Presenter。負責「View 與 Model 層之間的控制與交互」。
廢話不多說了,下面上一個簡單的例子,體驗一下MVP設計模式:
這裏模擬一下用戶登錄的場景,輸入賬號和密碼,後臺請求驗證賬號密碼是否正確,正確的話就直接登錄成功。
首先看一下代碼的層級結構:
這裏我麼的bean下面的就相當於我們model層下面封裝好的數據實體,biz下面就是我們的登陸的業務邏輯,presenter下面負責View和Model之間的交互。
User實體類的代碼:就兩個參數,一個登陸賬號,一個登陸密碼
package com.guannan.mvpdemo.bean;
/**
* Created by guannan on 2016/10/11.
*/
public class User {
private String account;
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
}
biz(業務邏輯層的代碼),這裏我們有一個登陸的需求所以我們提供一個登陸的接口IUserLogin,下面有一個login方法,假如我們有其他登陸相關的方法可以在這裏面進行添加
package com.guannan.mvpdemo.biz;
/**
* Created by guannan on 2016/10/11.
*/
public interface IUserLogin {
public void login(String username,String password,OnLoginListener loginListener);
}
然後我們的OnLoginListener下面使我們登陸成功以後所回調的方法,這個接口作爲我們和Presenter層的交互
package com.guannan.mvpdemo.biz;
import com.guannan.mvpdemo.bean.User;
/**
* Created by guannan on 2016/10/11.
*/
public interface OnLoginListener {
void loginSuccess(User user); //登錄成功
void loginFaild(); //登錄失敗
}
最後的UserLogin實現IUserLogin完成我們整個登錄的業務邏輯
package com.guannan.mvpdemo.biz;
import com.guannan.mvpdemo.bean.User;
/**
* Created by guannan on 2016/10/11.
*/
public class UserLogin implements IUserLogin {
@Override
public void login(final String username, final String password, final OnLoginListener loginListener) {
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
if("zgn".equals(username) && "123".equals(password)){
User user=new User();
user.setAccount(username);
user.setPassword(password);
loginListener.loginSuccess(user); //登錄成功
}else{
loginListener.loginFaild(); //登錄失敗
}
}
}).start();
}
}
這裏重點看一個LoginPresenter所完成的操作,這裏調用了UserLogin裏面的login方法,並通過OnLoginListener的接口回調進行登錄成功和失敗的操作。
package com.guannan.mvpdemo.presenter;
import android.content.Intent;
import android.os.Handler;
import com.guannan.mvpdemo.SuccessActivity;
import com.guannan.mvpdemo.bean.User;
import com.guannan.mvpdemo.biz.IUserLogin;
import com.guannan.mvpdemo.biz.OnLoginListener;
import com.guannan.mvpdemo.biz.UserLogin;
import com.guannan.mvpdemo.view.ILoginView;
/**
* Created by guannan on 2016/10/11.
*/
public class LoginPresenter {
IUserLogin mIUserLogin;
ILoginView mILoginView;
private Handler mHandler=new Handler();
public LoginPresenter(ILoginView iLoginView){
this.mIUserLogin=new UserLogin();
this.mILoginView=iLoginView;
}
public void login(){
mIUserLogin.login(mILoginView.getUserName(), mILoginView.getPassword(), new OnLoginListener() {
@Override
public void loginSuccess(User user) {
mHandler.post(new Runnable() {
@Override
public void run() {
mILoginView.clearPassword();
mILoginView.clearUsername();
Intent intent=new Intent(mILoginView.getActivity(), SuccessActivity.class);
mILoginView.getActivity().startActivity(intent);
mILoginView.getActivity().finish();
}
});
}
@Override
public void loginFaild() {
}
});
}
}
另外我們登錄成功或者失敗後需要對View層的Activity的界面進行一些操作,這裏提供了另外一個接口ILoginView,這裏主要是LoginPresenter層對UI層的一些界面操作(獲取賬號getUsername(),獲取密碼getPassword(),清空賬號clearUsername(),清空密碼clearPassword())。
package com.guannan.mvpdemo.view;
import android.app.Activity;
/**
* Created by guannan on 2016/10/11.
*/
public interface ILoginView {
public String getUserName();
public String getPassword();
public void clearUsername();
public void clearPassword();
public Activity getActivity();
}
Presenter層和View層的交互就是通過接口回調的方式,Model層和Presenter層的交互可以通過接口回調的方式,當然也可以採用EventBus,otto等方式。這裏不再介紹。
好久沒寫博客了,就寫到這裏,大神請飄過,歡迎吐槽~
參考資料:
https://zhuanlan.zhihu.com/p/20358928
https://www.zhihu.com/question/35185744
http://blog.csdn.net/lmj623565791/article/details/46596109
http://rocko.xyz/2015/02/06/Android%E4%B8%AD%E7%9A%84MVP/