Android的MVP模式講解
阿新 • • 發佈:2018-11-30
UI層越來越複雜,為了減輕了UI層的責任,也是為了更好地細分檢視(View)與模型(Model)的功能,讓View專注於處理數 據的視覺化以及與使用者的互動,讓Model只關係資料的處理,MVP(Model-View-Presenter)模式應運而生。每個人對MVP模式都有一定的理解,此篇僅供參考交流。
(1)View:負責繪製UI元素、與使用者進行互動(View interface與Presenter進行互動,降低耦合);(2)Model:依然是業務邏輯和實體模型、操縱資料(有時也實現一個Model interface用來降低耦合);
(3)Presenter:作為View與Model互動的中間紐帶,負責完成View於Model間的互動(處理與使用者互動的負責邏輯)
專案Demo結構圖:
(1)首先我們需要一個Bean
public class LoginUserBean { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }
(2)View的介面,需要用到的方法:
public interface LoginView {
void clearUsername();
void clearPassword();
void setUsernameError();
void setPasswordError();
void navigateToHome();
}
(3)LoginActivity實現View介面
public class LoginActivity extends Activity implements LoginView,OnClickListener {
private ProgressBar progressBar;
private EditText username;
private EditText password;
private Button btn_login;
private LoginPresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
progressBar = (ProgressBar) findViewById(R.id.progress);
username = (EditText) findViewById(R.id.username);
password = (EditText) findViewById(R.id.password);
btn_login=(Button) findViewById(R.id.button);
btn_login.setOnClickListener(this);
presenter = new LoginPresenterImpl(this);
}
@Override
public void onClick(View v) {
presenter.validateCredentials(username.getText().toString(), password.getText().toString());
}
@Override
public void navigateToHome() {
//登入成功,跳轉主頁
//Intent intent=new Intent(this,MainActivity.class);
//startActivity(intent);
Toast.makeText(this,"成功,跳轉",Toast.LENGTH_SHORT).show();
}
@Override
public void clearUsername() {
username.setText("");
}
@Override
public void clearPassword() {
password.setText("");
}
@Override
public void setUsernameError() {
username.setError(getString(R.string.username_error));
}
@Override
public void setPasswordError() {
password.setError(getString(R.string.password_error));
}
@Override
protected void onDestroy() {
presenter.onDestroy();
super.onDestroy();
}
}
(4)Model介面:
public interface LoginModel {
void login(String username, String password, OnLoginFinishedListener listener);
}
(5)Model介面的實現類:
public class LoginModelImpl implements LoginModel{
@Override
public void login(final String username, final String password, final OnLoginFinishedListener listener) {
new Handler().postDelayed(new Runnable() {
//模擬耗時登入
@Override
public void run() {
//此處判斷使用者密碼
if (TextUtils.isEmpty(username)){
listener.onUsernameError();//model層裡面回撥listener
}
if (TextUtils.isEmpty(password)){
listener.onPasswordError();
}
//此處成功,(真實應該網路返回成功,這裡省略)
//呼叫回撥方法,通過LoginPresenter操作ui層,跳轉到主頁
listener.onSuccess();
}
}, 2000);
}
}
(6)Presenter橋樑介面:
public interface LoginPresenter {
void validateCredentials(String username, String password);
void onDestroy();
}
(7)Presenter現實類,實現回撥OnLoginFinishedListener,M層通過回撥方法操作Ui層:
public class LoginPresenterImpl implements LoginPresenter, OnLoginFinishedListener {
private LoginView loginView;
private LoginModel loginModel;
public LoginPresenterImpl(LoginView loginView) {
this.loginView = loginView;
this.loginModel = new LoginModelImpl();
}
//ui層呼叫
@Override
public void validateCredentials(String username, String password) {
loginModel.login(username, password, this);
}
@Override
public void onSuccess() {
if (loginView != null) {
//M層回撥後,這裡操作Ui層介面的跳轉
loginView.navigateToHome();
}
}
@Override
public void onDestroy() {
loginView = null;
}
@Override
public void onUsernameError() {
if (loginView != null) {
loginView.setUsernameError();
loginView.clearUsername();
}
}
@Override
public void onPasswordError() {
if (loginView != null) {
loginView.setPasswordError();
loginView.clearPassword();
}
}
@Override
public void clearUsername() {
// TODO Auto-generated method stub
}
@Override
public void clearPassword() {
// TODO Auto-generated method stub
}
}
(8)回撥介面:
public interface OnLoginFinishedListener {
void clearUsername();
void clearPassword();
void onUsernameError();
void onPasswordError();
void onSuccess();
}
登入流程解析:
1-首先是點選了按鈕,在Ui層LoginActivity呼叫橋樑實現類LoginPresenterImpl的方法validateCredentials()
@Override
public void onClick(View v) {
presenter.validateCredentials(username.getText().toString(), password.getText().toString());
}
2-LoginPresenterImpl類操作M層
@Override
public void validateCredentials(String username, String password) {
loginModel.login(username, password, this);
}
3-LoginModelImpl中的login,當後臺資料返回成功時,呼叫回撥方法操作LoginPresenterImpl類onSuccess方法,
這裡onSuccess方法中loginView.navigateToHome()就是操作UI層,達到跳轉主頁.
@Override
public void login(final String username, final String password, final OnLoginFinishedListener listener) {
new Handler().postDelayed(new Runnable() {
//模擬耗時登入
@Override
public void run() {
//此處判斷使用者密碼
if (TextUtils.isEmpty(username)){
listener.onUsernameError();//model層裡面回撥listener
}
if (TextUtils.isEmpty(password)){
listener.onPasswordError();
}
//此處成功,(真實應該網路返回成功,這裡省略)
//呼叫回撥方法,通過LoginPresenter操作ui層,跳轉到主頁
listener.onSuccess();
}
}, 2000);
}
4-loginView.navigateToHome()方法操作的UI層如下:
@Override
public void navigateToHome() {
//登入成功,跳轉主頁
//Intent intent=new Intent(this,MainActivity.class);
//startActivity(intent);
Toast.makeText(this,"成功,跳轉",Toast.LENGTH_SHORT).show();
}
總結:通過上面流程可以看出,View只負責處理與使用者進行互動,並把資料相關的邏輯操作都扔給了Presenter去做。而Presenter呼叫Model處理完資料之後,再通過IUserView更新View顯示的資訊。每個人對MVP模式都有一定的理解,此篇僅供參考交流。