標籤:
1,相信大家對mvp模式都很熟悉了,M-Model-模型、V-View-視圖、C-Controller-控制器。MVP作為MVC的版本演化,與MVC的意義類似:M-Model-模型、V-View-視圖、P-Presenter-表示器。從MVC和MVP兩者結合來看,Controlller/Presenter在MVC/MVP中都起著邏輯控制處理的角色,起著控制各商務程序的作用。而 MVP與MVC最不同的一點是M與V是不直接關聯的也是就Model與View不存在直接關係,這兩者之間間隔著的是Presenter層,其負責調控 View與Model之間的間接互動。在 Android中很重要的一點就是對UI的操作基本上需要非同步進行也就是在MainThread中才能操作UI,所以對View與Model的切斷分離是 合理的。此外Presenter與View、Model的互動使用介面定義互動操作可以進一步達到松耦合也可以通過介面更加方便地進行單元測試。下面是對應的兩張圖(左圖為mvc,右圖為mvp):
可以看到最明顯的區別是mvc是允許model和view互動的,而mvp中model和view中的互動是由presenter完成的,presenter和view的互動是通過介面來實現的。
2,mvp的實現應用 (例子是大神部落格寫的,自己只是拿過來來寫一下實現的思路,畢竟還是小菜鳥的層級)
先看一下要實現的效果:
再看一下我們工程的目錄:
由我們上面的功能需要可以看出,這是一個最常見的登入功能,所以首先我們要建立一個User類,,包含使用者名稱和密碼,用於對應使用者輸入的使用者資訊
① Model層
User.java
package com.wangjitao.simplelogindemo.bean;/** * Created by wangjitao on 2016/5/12. * 使用者登入bean */public class User { 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; }}
從上面所給的功能可以看出我們主要是要實現登入功能的,所以至少有一個login()方法
IUserBIZ.java
package com.wangjitao.simplelogindemo.inter;import com.wangjitao.simplelogindemo.listener.OnLoginListener;/** * Created by wangjitao on 2016/5/12. */public interface IUserBIZ { public void login(String username ,String password ,OnLoginListener loginListener);}
它的實作類別 UserBIZ.java ,在實作類別中我們類比一個登陸的耗時操作,然後在登入成功的寫了一個回調類OnLoginListener.java
UserBIZ.java
package com.wangjitao.simplelogindemo.inter;import com.wangjitao.simplelogindemo.bean.User;import com.wangjitao.simplelogindemo.listener.OnLoginListener;/** * Created by jh on 2016/5/12. */public class UserBIZ implements IUserBIZ{ @Override public void login(final String username, final String password, final OnLoginListener loginListener) { //開啟子線程類比登入耗時操作 new Thread(){ @Override public void run() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } //類比登入成功 if("wjt".equals(username) && "123456".equals(password)){ User user = new User(); user.setUsername(username); user.setPassword(password); loginListener.loginSuccess(user); }else { loginListener.loginFailed(); } } }.start(); }}
OnLoginListener.java
package com.wangjitao.simplelogindemo.listener;import com.wangjitao.simplelogindemo.bean.User;/** * Created by wangjitao on 2016/5/12. */public interface OnLoginListener { void loginSuccess(User user) ; void loginFailed();}
②View 層
從我們看到的介面我們可以看到,使用者一共有兩個按鈕,一個是login,那麼需要兩個方法來擷取使用者名稱和密碼
String getUserName();String getPassword();
然後是一個clear按鈕,這時候我們要提供兩個方法去清空輸入框的內容
void clearUserName();void clearPassword();
然後當使用者正在登陸的時候,我們需要一個使用者的等待,這時候我們需要加一個進度的提示條
void clearUserName();void clearPassword();
然後是使用者登入後的一些提示,當登陸成功,讓使用者跳轉到下一個介面,當登入失敗提示使用者使用者名稱或密碼錯誤
void toMainActivity(User user); void showFailedError();
所以view的介面如下:
package com.wangjitao.simplelogindemo.view;import com.wangjitao.simplelogindemo.bean.User;/** * Created by jh on 2016/5/12. */public interface IUserLoginView { String getUserName(); String getPassword(); void showLoading(); void dismissLoading(); void toMainActivity(User user); void showFailedError(); void clearUserName(); void clearPassword();}
然後Activity來實現這個介面的方法(Activity也可以當做一個view層)
package com.wangjitao.simplelogindemo;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.ProgressBar;import android.widget.Toast;import com.wangjitao.simplelogindemo.bean.User;import com.wangjitao.simplelogindemo.presenter.UserLoginPresenter;import com.wangjitao.simplelogindemo.view.IUserLoginView;public class MainActivity extends AppCompatActivity implements IUserLoginView{ private EditText editText_username ,editText_password ; private Button button_login ,button_clean ; private ProgressBar progressBar ; private UserLoginPresenter mUserLoginPresenter = new UserLoginPresenter(this); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); } private void initView() { editText_username = (EditText)findViewById(R.id.editText_username); editText_password = (EditText)findViewById(R.id.editText_password); button_login = (Button)findViewById(R.id.button_login); button_clean = (Button)findViewById(R.id.button_clean); progressBar = (ProgressBar)findViewById(R.id.progressBar); button_login.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mUserLoginPresenter.login(); } }); button_clean.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mUserLoginPresenter.clear(); } }); } @Override public String getUserName() { return editText_username.getText().toString(); } @Override public String getPassword() { return editText_password.getText().toString(); } @Override public void showLoading() { progressBar.setVisibility(View.VISIBLE); } @Override public void dismissLoading() { progressBar.setVisibility(View.GONE); } @Override public void toMainActivity(User user) { Toast.makeText(MainActivity.this ,"登入成功:歡迎回來"+user.getUsername(),Toast.LENGTH_SHORT).show(); } @Override public void showFailedError() { Toast.makeText(MainActivity.this ,"登入失敗",Toast.LENGTH_SHORT).show(); } @Override public void clearUserName() { editText_username.setText(""); } @Override public void clearPassword() { editText_password.setText(""); }}
③Persenter
這個用與處資料和視圖的互動,我們的這個應用主要是login和clear ,所以代碼如下:
package com.wangjitao.simplelogindemo.presenter;import android.os.Handler;import com.wangjitao.simplelogindemo.bean.User;import com.wangjitao.simplelogindemo.inter.IUserBIZ;import com.wangjitao.simplelogindemo.inter.UserBIZ;import com.wangjitao.simplelogindemo.listener.OnLoginListener;import com.wangjitao.simplelogindemo.view.IUserLoginView;/** * Created by wangjitao on 2016/5/12. */public class UserLoginPresenter { private IUserBIZ userBIZ ; private IUserLoginView userLoginView ; private Handler mHandler = new Handler(); public UserLoginPresenter(IUserLoginView userLoginView){ this.userLoginView = userLoginView ; userBIZ = new UserBIZ(); } public void login(){ userLoginView.showLoading(); userBIZ.login(userLoginView.getUserName(), userLoginView.getPassword(), new OnLoginListener() { @Override public void loginSuccess(final User user) { mHandler.post(new Runnable() { @Override public void run() { userLoginView.toMainActivity(user); userLoginView.dismissLoading(); } }); } @Override public void loginFailed() { mHandler.post(new Runnable() { @Override public void run() { userLoginView.showFailedError(); userLoginView.dismissLoading(); } }); } }); } public void clear(){ userLoginView.clearUserName(); userLoginView.clearPassword(); }}
Presenter大致就是從View中擷取需要的參數,交給Model去執行業務方法,執行的過程中需要的反饋,以及結果,再讓View進行做對應的顯示。
這樣我們的demo就寫完了 ,感覺還是很有成就感的嘛。
Android -- 初探MVP模式