Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android進階 MVP設計模式實例

Android進階 MVP設計模式實例

編輯:關於Android編程

MVP(Model View Presenter)的設計模式是從MVC中演化而來的,主要作用是能夠:
劃分模塊職責,
降低模塊耦合
易測試,提高代碼復用

Model:數據:負責數據的檢索
View: 視圖:負責視圖的繪制,和用戶的交互
presenter: 控制器:負責在Model和View之間交互,負責兩者業務的邏輯處理

與MVC的區別:

在MVC中,在Controller中,有View和Model的部分處理邏輯,在View處理時間的過程中,也有Model操作的過程,
該模式看起來模式簡單,層級關系不多,而且代碼量少,但是大部分邏輯都雜糅到了一起,
在測試和調試的過程中較之MVP而言很不方便
在MVC中,數據,控制器,視圖之間互相操作的關系是這樣的:
MVC模式圖,轉自hongyang的博客

而在MVP中,presenter單線操作數據Model部分的數據,
同樣的presenter也是單線的操作視圖View模塊的東西,但是中間是是通過調用接口的方式,
當View界面和數據有交互的時候,再通過接口調用Presenter,再由Presenter調用Model來進行數據的改變
在MVP中,數據,控制器,視圖之間相互操作的關系是這樣的:

圖片來自hognyang的博客

Android代碼示例

簡單的演示一個登陸操作的界面,用戶輸入用戶名密碼,然後模擬操作訪問服務器驗證用戶名密碼的操作,此過程顯示進度條,登陸成功之後顯示成功界面,失敗提示失敗信息

簡單的看一下界面:
activity_user_login.xml:




    
    
    
    

界面效果如下:

這裡寫圖片描述

程序運行結果預覽:
這裡寫圖片描述

界面寫好之後,開始分析該程序的數據和功能:
首先,需要有一個JavaBean對象User,保存username 和password字段
需要String類型的username和password

package com.jishihuitong.mvpdemo.bean;

/**
 * Created by hss on 2016/8/2.
 */
public class User {
    private String username;
    private String password;

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

然後根據視圖,肯定要有一個login的方法,在MVP中presenter操作model和view的過程都是使用接口的,所以要有一個IUserModel和UserModelImpl繼續完成

IUserModel類

package com.jishihuitong.mvpdemo.model;

/**
 * Created by hss on 2016/8/2.
 */
public interface IUserModel {

    /**
     * 登錄數據模塊的操作
     * @param username 用戶名
     * @param password 密碼
     * @param onLoginListener 登錄監聽
     */
    public void login(String username,String password,OnLoginListener onLoginListener);
}

IUserModel實現類

package com.jishihuitong.mvpdemo.model;

import com.jishihuitong.mvpdemo.bean.User;

/**
 * Created by hss on 2016/8/2.
 */
public class UserModelImpl implements IUserModel {
    @Override
    public void login(final String username, final String password, final OnLoginListener onLoginListener) {
        new Thread(){
            @Override
            public void run() {
                try {
                //模擬從網絡加載數據,需要時間
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if("username".equals(username) && "password".equals(password)){
                    User user = new User();
                    user.setUsername(username);
                    user.setPassword(password);
                    onLoginListener.loginSuccess(user);
                }else{
                    onLoginListener.loginFailed();
                }
            }
        }.start();
    }
}

登錄成功或者失敗的監聽

package com.jishihuitong.mvpdemo.model;

import com.jishihuitong.mvpdemo.bean.User;

/**
 * Created by hss on 2016/8/2.
 */
public interface OnLoginListener {
    /**
     * 登錄成功
     * @param user user對象
     */
    public void loginSuccess(User user);

    /**
     * 登錄失敗
     */
    public void loginFailed();
}

View層,上面說到,MVP設計模式中,調用View層的方法都是通過接口調用的,
所以我們需要顯示定義一個View的接口ILoginVeiw,在該接口中需要有什麼方法呢?
首先需要

getUsername();
getPassword();

清空輸入框內容的方法

clearUsername();
clearPassword();

登錄成功和登錄失敗的方法

toMainActivity(User user);
showFailedError();

顯示進度和隱藏進度的方法

showLoading();
hideLoading();

所以綜合上述表述,寫出來的ILoginView接口應該是這樣的:

package com.jishihuitong.mvpdemo.view;

import com.jishihuitong.mvpdemo.bean.User;

/**
 * Created by hss on 2016/8/2.
 */
public interface IUserLoginView {
    /**
     * View層接口獲取用戶名的方法
     * @return 輸入的用戶名
     */
    public String getUserName();

    /**
     * View層接口獲取密碼的方法
     * @return 輸入的密碼
     */
    public String getPassword();

    /**
     * View層清除用戶名
     */
    public void clearUserName();

    /**
     * View層清除密碼的方法
     */
    public void clearPassword();

    /**
     * View層登錄成功的方法
     * @param user user對象
     */
    public void toMainActivity(User user);

    /**
     * View層顯示登錄失敗的方法
     */
    public void showFailedError();

    /**
     * View層顯示進度條的方法
     */
    public void showLoading();

    /**
     * View層隱藏進度條的方法
     */
    public void hideLoading();
}

而加載布局的一個類顯然就是View層的了,該類要實現ILoginView接口,並且實現裡面的方法:
然後登錄操作,需要使用present來執行,
UserLoginActivity.java

package com.jishihuitong.mvpdemo.view;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.jishihuitong.mvpdemo.R;
import com.jishihuitong.mvpdemo.bean.User;
import com.jishihuitong.mvpdemo.presenter.UserLoginPresenter;

/**
 * 登錄界面主activity IView的實現類,
 */
public class UserLoginActivity extends AppCompatActivity implements IUserLoginView {

    private EditText id_et_username;
    private EditText id_et_password;
    private Button id_btn_login;
    private Button id_btn_clear;
    private UserLoginPresenter mUserLoginPrestener = new UserLoginPresenter(this);
    private ProgressBar id_progressbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_user_login);
        initView();
    }

    /**
     * 初始化控件
     */
    private void initView() {
        id_et_username = (EditText) findViewById(R.id.id_et_username);
        id_et_password = (EditText) findViewById(R.id.id_et_password);
        id_btn_login = (Button) findViewById(R.id.id_btn_login);
        id_btn_clear = (Button) findViewById(R.id.id_btn_clear);
        id_progressbar = (ProgressBar) findViewById(R.id.id_progressbar);

        id_btn_login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//              presenter控制邏輯 登錄操作
                mUserLoginPrestener.login();
            }
        });

        id_btn_clear.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mUserLoginPrestener.clear();
            }
        });
    }

    @Override
    public String getUserName() {
        return id_et_username.getText().toString();
    }

    @Override
    public String getPassword() {
        return id_et_password.getText().toString();
    }

    @Override
    public void clearUserName() {
        id_et_username.setText("");
    }

    @Override
    public void clearPassword() {
        id_et_password.setText("");
    }

    @Override
    public void toMainActivity(User user) {
        Toast.makeText(getApplicationContext(),getUserName()+"登錄成功",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showFailedError() {
        Toast.makeText(getApplicationContext(),getUserName()+"登錄失敗",Toast.LENGTH_SHORT).show();
    }

    @Override
    public void showLoading() {
        id_progressbar.setVisibility(View.VISIBLE);
    }

    @Override
    public void hideLoading() {
        id_progressbar.setVisibility(View.INVISIBLE);
    }
}

UserLoginPresenter.java

package com.jishihuitong.mvpdemo.presenter;

import android.os.Handler;

import com.jishihuitong.mvpdemo.bean.User;
import com.jishihuitong.mvpdemo.model.IUserModel;
import com.jishihuitong.mvpdemo.model.OnLoginListener;
import com.jishihuitong.mvpdemo.model.UserModelImpl;
import com.jishihuitong.mvpdemo.view.IUserLoginView;

/**
 * Created by hss on 2016/8/2.
 */
public class UserLoginPresenter {
    private IUserModel userModel;
    private IUserLoginView userLoginView;
    private Handler mHandler = new Handler() {
    };

    public UserLoginPresenter(IUserLoginView userLoginView) {
        this.userModel = new UserModelImpl();
        this.userLoginView = userLoginView;
    }

    /**
     * 登錄操作
     */
    public void login() {
//      設置進度條可見
        userLoginView.showLoading();
        //數據控制器控制model操作登錄
        userModel.login(userLoginView.getUserName(), userLoginView.getPassword(), new OnLoginListener() {
            @Override
            public void loginSuccess(final User user) {
                //需要在UI線程執行
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        userLoginView.toMainActivity(user);
                        userLoginView.hideLoading();
                    }
                });
            }

            @Override
            public void loginFailed() {
                //需要在UI線程執行
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        userLoginView.showFailedError();
                        userLoginView.hideLoading();
                    }
                });
            }
        });
    }

    /**
     * 清除所有數據的方法
     */
    public void clear() {
        userLoginView.clearPassword();
        userLoginView.clearUserName();
    }
}

總體來說,雖然說代碼的層次增加了,代碼量也增加了,但是仔細看看,是不是代碼感覺特別明朗,層次感特別清晰呢,該模式主要適用於數據和view交互比較多的模塊

點擊下載代碼

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved