初識android設計模式—MVP

一、什麼是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/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章