Android MVP開發模式詳解

jopen 8年前發布 | 40K 次閱讀 MVC模式 安卓開發 Android開發 移動開發

(一).前言:

今天我們的項目繼續更新,今天我們主要講解MVP開發模式以及具體實例。

FastDev4Android框架項目地址: https://github.com/jiangqqlmj/FastDev4Android

(二).簡介:

MVP(Model View Presenter)模式是著名的MVC(Model View Controller)模式的一個演化版本,目前它在Android應用開發中越來越重要了。初看起來我們會感覺增加了很多類接口代碼看起來更加清晰。

MVP模式可以分離顯示層和邏輯層,所以功能接口如何工作與功能的展示可以實現分離,MVP模式理想化地可以實現同一份邏輯代碼搭配不同的顯示界面。不過MVP不是一個結構化的模式,它只是負責顯示層而已,任何時候都可以在自己的項目結構中使用MVP模式。(不局限于Android項目開發)

因為MVP其實就是從MVC模式演化產生的,那么我們先看一下著名的MVC模式:

  •       View:對應于布局文件
  •       Model:業務邏輯和實體模型
  •      Controller:控制器,Android中對應于Activity

對應的交互圖如下:

雖然Android系統應用開發本身是遵循MVC開發模式的,但是我們仔細看一下View層和Activity,具體view布局文件中的數據綁定和事件處理的方法代碼都是冗余在Activity中的,所以我們經常看可以看到Activity類動不動就是少則九百行,多則上千甚至幾千行。那么現在的演化升級版本的MVP的模式又是怎么樣的呢?MVP模式會引入  Presenter層,該機型復雜完成View層和Model層的交互,那么具體MVP對應如下:

  •       View:View通常來說是由Activity實現的,它會包含一個Presenter的引用,View要做的就只是在每次有接口調用的時候(比如按鈕點擊后)調用Presenter的方法。
  •        Model:業務邏輯和實體模型
  •       Presenter:主要作為溝通View和Model的橋梁,它從Model層檢索數據后,返回給View層,但是不像MVC結構,因為它也可以決定與View層的交互操作。

數據交互圖如下:

觀察上面兩個模式的交互圖,是不是MVP模式更加清晰簡單啊!

(三).MVC和MVP區別:

我們來具體看一下下面兩張對比,就可以看來具體區別了:

觀察上圖我們可以發現MVP模式中,View 和Model的交互是通過Presenter來進行完成,這樣統一管理,邏輯會更加清晰。

(四).MVP模式例子講解:

4.1.具體實現功能需求:我們是用MVP模式來進行實現用戶登錄操作.

4.2.例子實例如下:

4.3.項目代碼框架如下:

4.4.代碼具體實現:

4.4.1.Model層:Bean類(Entity),PersonBean類,然后在業務邏輯類中有登錄方法,同時把登錄成功狀態回調接口傳入進入,具體如下:

package com.chinaztt.fda.entity;
 /** * 當前類注釋:用戶信息實體類 * 項目名:FastDev4Android * 包名:com.chinaztt.fda.entity * 作者:江清清 on 15/10/27 14:13 * 郵箱:jiangqqlmj@163.com * QQ: 781931404 * 公司:江蘇中天科技軟件技術有限公司 */
 public class PersonBean {
 private String username;
 private String password;
 public PersonBean() {
 }

 public PersonBean(String username, String password) {
 this.username = username;
 this.password = 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;
 }

 @Override
 public String toString() {
 return "PersonBean{" +
 "username='" + username + '\'' +
 ", password='" + password + '\'' +

 '}';
 }
 }
public interface IPersonBiz {
 void login(String username,String password,LoginRequestCallBack valueCallBack);
 }
package com.chinaztt.fda.biz.imp;
 import com.chinaztt.fda.biz.IPersonBiz;
 import com.chinaztt.fda.biz.LoginRequestCallBack;
 import com.chinaztt.fda.entity.PersonBean;
 import com.chinaztt.fda.utils.Log;
 /** * 當前類注釋:用戶相關業務邏輯實現類 * 項目名:FastDev4Android * 包名:com.chinaztt.fda.biz.imp * 作者:江清清 on 15/10/27 16:33 * 郵箱:jiangqqlmj@163.com * QQ: 781931404 * 公司:江蘇中天科技軟件技術有限公司 */
 public class PersonBizImp implements IPersonBiz{
 private static final  String TAG="PersonBizImp";
 @Override
 public void login(final String username, final String password, final LoginRequestCallBack valueCallBack) {
 Log.d(TAG,"username:"+username+",password:"+password);
 new Thread(new Runnable() {
 @Override
 public void run() {
 try {
 Thread.sleep(4500);
 } catch (InterruptedException e) {
 e.printStackTrace();
 }
 //進行開始登錄,這邊應該進行請求服務器,進行數據驗證
 if(username.equals("jiangqq")&&password.equals("12345")){
 valueCallBack.loginSuccess(new PersonBean(username,password));
 }else{
 valueCallBack.loginFailed();
 }
 }
 }).start();
 }
 }
package com.chinaztt.fda.biz;
 import com.chinaztt.fda.entity.PersonBean;
 /** * 當前類注釋:登錄請求結果回調 * 項目名:FastDev4Android * 包名:com.chinaztt.fda.biz * 作者:江清清 on 15/10/27 19:50 * 郵箱:jiangqqlmj@163.com * QQ: 781931404 * 公司:江蘇中天科技軟件技術有限公司 */
 public interface LoginRequestCallBack {
 //登錄成功回調方法
 void loginSuccess(PersonBean personBean);
 //登錄失敗回調方法
 void loginFailed();
 }

4.4.2.View層:該通過Presenter與View進行交互,這邊需要定義一個接口ILoginView:

package com.chinaztt.fda.ui.view;
 import com.chinaztt.fda.entity.PersonBean;
 /** * 當前類注釋:登錄頁面 相關操作 功能接口 * 項目名:FastDev4Android * 包名:com.chinaztt.fda.ui.view * 作者:江清清 on 15/10/27 16:35 * 郵箱:jiangqqlmj@163.com * QQ: 781931404 * 公司:江蘇中天科技軟件技術有限公司 */
 public interface ILoginView {
 //獲取用戶名
 String getUserName();
 //獲取密碼
 String getPassword();

 void showSuccessInfo(PersonBean personBean);
 void showFailedInfo();
 }

有了上面的接口之后,我們就需要寫我們的實現類Activity了,就非常簡單了

package com.chinaztt.fda.test;
 import android.os.Bundle;
 import android.view.View;
 import android.widget.Button;
 import android.widget.EditText;
 import com.chinaztt.fda.entity.PersonBean;
 import com.chinaztt.fda.presenter.LoginPresenter;
 import com.chinaztt.fda.ui.R;
 import com.chinaztt.fda.ui.base.BaseActivity;
 import com.chinaztt.fda.ui.view.ILoginView;
 import com.chinaztt.fda.utils.Log;
 import org.androidannotations.annotations.EActivity;
 /** * 當前類注釋:MVP開發模式實例 * 項目名:FastDev4Android * 包名:com.chinaztt.fda.test * 作者:江清清 on 15/10/27 13:38 * 郵箱:jiangqqlmj@163.com * QQ: 781931404 * 公司:江蘇中天科技軟件技術有限公司 */
 @EActivity
 public class MVPTestActivity extends BaseActivity implements ILoginView{
 private static  final  String TAG="MVPTestActivity";
 private EditText ed_username;
 private EditText ed_password;
 private Button btn_login;
 private LoginPresenter mLoginPresenter;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.mvp_test_layout);
 ed_username=(EditText)this.findViewById(R.id.ed_username);
 ed_password=(EditText)this.findViewById(R.id.ed_password);
 btn_login=(Button)this.findViewById(R.id.btn_login);
 mLoginPresenter=new LoginPresenter(this);
 btn_login.setOnClickListener(new View.OnClickListener() {
 @Override
 public void onClick(View v) {
 mLoginPresenter.loginSystem();
 }
 });
 }
 /** * 進行返回用戶名信息 * @return */
 @Override
 public String getUserName() {
 return ed_username.getText().toString().trim();
 }
 /** * 進行返回用戶密碼信息 * @return */
 @Override
 public String getPassword() {
 return ed_password.getText().toString().trim();
 }
 /** * 登錄成功 回調 * @param personBean */
 @Override
 public void showSuccessInfo(PersonBean personBean) {
 Log.d(TAG,"showSuccessInfo:"+personBean.toString());
 showToastMsgShort("登錄成功:"+personBean.toString());
 }
 /** * 登錄失敗 回調 */
 @Override
 public void showFailedInfo() {
 Log.d(TAG,"showFailedInfo...");
 showToastMsgShort("登錄失敗...");
 }
 }

最后還少一個交互橋梁Presenter:4.4.3.Presenter層:作為Model和View之間的交互橋梁,在本例中進行執行登錄操作,然后去Model業務中執行登錄,最后把登錄結果信息返回給View層,就是這么簡單:

package com.chinaztt.fda.presenter;
 import android.os.Handler;
 import com.chinaztt.fda.biz.IPersonBiz;
 import com.chinaztt.fda.biz.LoginRequestCallBack;
 import com.chinaztt.fda.biz.imp.PersonBizImp;
 import com.chinaztt.fda.entity.PersonBean;
 import com.chinaztt.fda.ui.view.ILoginView;
 import com.chinaztt.fda.utils.Log;
 /** * 當前類注釋:負責完成登錄界面View于Model(IPersonBiz)間的交互 * 項目名:FastDev4Android * 包名:com.chinaztt.fda.presenter * 作者:江清清 on 15/10/27 16:36 * 郵箱:jiangqqlmj@163.com * QQ: 781931404 * 公司:江蘇中天科技軟件技術有限公司 */
 public class LoginPresenter {
 private static final  String TAG="LoginPresenter";
 private ILoginView mLoginView;
 private IPersonBiz mPersonBiz;
 private Handler mHandler=new Handler();
 public LoginPresenter(ILoginView view) {
 mLoginView = view;
 mPersonBiz = new PersonBizImp();
 }
 public void loginSystem(){
 mPersonBiz.login(mLoginView.getUserName(), mLoginView.getPassword(), new LoginRequestCallBack() {
 /** * 登錄成功 * @param personBean */
 @Override
 public void loginSuccess(final PersonBean personBean) {
 Log.d(TAG, "登錄成功:" + personBean.toString());
 mHandler.post(new Runnable() {
 @Override
 public void run() {
 mLoginView.showSuccessInfo(personBean);
 }
 });
 }
 /** * 登錄失敗 */
 @Override
 public void loginFailed() {
 Log.d(TAG,"登錄失敗...");
 mHandler.post(new Runnable() {
 @Override
 public void run() {
 mLoginView.showFailedInfo();;
 }
 });
 }
 });
 }
 }

到此我們的MVP模式的例子就大體完成了,看一下上面的效果演示就OK了。

我們的項目已經配置集成了MVP Demo的例子.

歡迎大家去Github站點進行clone或者下載瀏覽: https://github.com/jiangqqlmj/FastDev4Android 同時歡迎大家star和fork整個開源快速開發框架項目~

尊重原創,轉載請注明:From Sky丶清(http://www.lcode.org) 侵權必究!

關注我的訂閱號(codedev123),每天分享移動開發技術(Android/IOS),項目管理以及博客文章!(歡迎關注,第一時間推送精彩文章)

關注我的微博,可以獲得更多精彩內容

來自: http://www.lcode.org/android-mvp開發模式詳解/

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!