安卓MVP

本文详细介绍了MVC和MVP两种软件设计模式的区别,重点在于它们在Android应用开发中的应用。MVC模式中,Controller直接与View交互,导致组件间耦合度过高。而MVP模式通过Presenter作为View和Model之间的桥梁,实现了解耦。文中通过登录功能的代码示例,展示了MVP模式的具体实现,包括Presenter、Model和View的接口定义及其实现,展示了如何通过Presenter协调Model的验证逻辑和View的反馈展示。

一、概述

MVC结构

M(model):业务逻辑和实体模型
V(view):布局文件
C(controller):Activity
说明:三层耦合在一起,会非常臃肿,难以扩展维护。

MVP结构

M(model):业务逻辑和实体模型
V(view):布局文件+Activity/Fragment+View组件+简单用户交互(不包含业务逻辑)
P(presenter):负责view和model的交互。
说明:presenter会将view和model分隔开,自己作为交互的桥梁,实现解耦。

二者中的model说明:业务逻辑和实体模型。
业务逻辑包含:网络请求、数据存储、数据流转、数据验证等等。
实体模型:bean对象。

交互

1、MVC是M和V可以直接交互。
2、MVP是M和V不能直接交互,它们是通过P进行交互的。
在这里插入图片描述

二、代码示例

使用最常见的登录案例,代码实现过程描述:Presenter主要用于分离view和model,它和两层都有交互,所以持有view和model的引用。当然view和model都需要和Presenter交互,他们分别持有Presenter的引用。
当用户点击登录时,view层要通过Presenter层的validatedLogin方法,实际调用model层的login方法验证登录;model层通过Presenter层的OnLoginFinishedListener的方法,将各种登录结果返回给view层展示出来。

1)Presenter

1.1 Presenter层 添加 view–>model的桥梁方法

public interface LoginPresenter {

    void validatedLogin(UserBean loginUser); //验证登陆信息

    void clear(); //释放资源
}

1.2 Presenter层 添加 model–>view的桥梁方法

public interface OnLoginFinishedListener {
    void onLoginFailedByAccountError();

    void onLoginFailedByPasswordError();

    void onLoginFailedByOtherError();

    void onLoginSuccess();
}

1.3 Presenter层 实现 view和model的真实交互。

public class LoginPresenterImpl implements LoginPresenter, OnLoginFinishedListener {
    private LoginModel loginModel = new LoginModelImpl(); // 持有Model层的引用
    private LoginView loginView;

    public LoginPresenterImpl(LoginView loginView) {
        this.loginView = loginView;
    }

    @Override
    public void validatedLogin(UserBean loginUser) {
        if (loginView != null) {
            loginView.showProgress();
        }
        loginModel.login(loginUser, this); // 调用Model层真实的登录验证方法,并传值过去。
    }

    @Override
    public void clear() {
        loginView = null;
    }

    @Override
    public void onLoginFailedByAccountError() {
        if (loginView != null) {
            loginView.hideProgress();
            loginView.onAccountError();
        }
    }

    @Override
    public void onLoginFailedByPasswordError() {
        if (loginView != null) {
            loginView.hideProgress();
            loginView.onPasswordError();
        }
    }

    @Override
    public void onLoginFailedByOtherError() {
        if (loginView != null) {
            loginView.hideProgress();
            loginView.onOtherError();
        }
    }

    @Override
    public void onLoginSuccess() {
        if (loginView != null) {
            loginView.hideProgress();
        }
    }
}

2)Model

2.1 Model层 创建 实体模型

public class UserBean {
    private String phoneNumber;
    private String passWord;

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public String getPassWord() {
        return passWord;
    }

    public void setPassWord(String passWord) {
        this.passWord = passWord;
    }
}

2.2 Model层 添加 登录验证的方法

public interface LoginModel {
    void login(UserBean loginUser, OnLoginFinishedListener listener);
}

2.3 Model层 实现 登录验证的方法

public class LoginModelImpl implements LoginModel {

    @Override
    public void login(UserBean loginUser, OnLoginFinishedListener listener) {
        final String phoneNumber = loginUser.getPhoneNumber();
        final String password = loginUser.getPassWord();
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                boolean error = false;
                if (TextUtils.isEmpty(phoneNumber)) {
                    listener.onLoginFailedByAccountError(); //回复登录验证结果
                    error = true;
                }
                if (TextUtils.isEmpty(password)) {
                    listener.onLoginFailedByPasswordError(); //回复登录验证结果
                    error = true;
                }
                if (!error) {
                    listener.onLoginSuccess(); ////回复登录验证结果
                }
            }
        }, 2000);
    }
}

3)View

3.1 View层 添加 展示登录结果的方法

public interface LoginView {
    void showProgress();

    void hideProgress();

    void onAccountError();

    void onPasswordError();

    void onOtherError();

    void loginSuccess();
}

3.2 View层 实现 展示登录结果的方法

public class LoginActivity extends AppCompatActivity implements LoginView {
    private LoginPresenter loginPresenter; //持有Presenter层的引用

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        loginPresenter = new LoginPresenterImpl(this);
        initView();
    }

    private void initView() {
        EditText editText_account = findViewById(R.id.editText_account);
        EditText editText_password = findViewById(R.id.editText_password);
        findViewById(R.id.button_login).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                UserBean userBean = new UserBean();
                userBean.setPhoneNumber(editText_account.getText().toString());
                userBean.setPassWord(editText_password.getText().toString());
                loginPresenter.validatedLogin(userBean); //调用Presenter层桥梁方法,并传真实数据过去。
            }
        });
    }

    @Override
    public void showProgress() {
        ToastUtil.show2Style(this,"显示进度条");
    }

    @Override
    public void hideProgress() {
        ToastUtil.show2Style(this,"隐藏进度条");
    }

    @Override
    public void onAccountError() {
        ToastUtil.show2Style(this,"账号错误");
    }

    @Override
    public void onPasswordError() {
        ToastUtil.show2Style(this,"密码错误");
    }

    @Override
    public void onOtherError() {
        ToastUtil.show2Style(this,"其他原因错误");
    }

    @Override
    public void loginSuccess() {
        ToastUtil.show2Style(this,"登陆成功!");
    }
}
### Android MVP 架构的使用方法与实现 #### MVC 架构模式的弊端 在传统的 Android 开发中,许多初学者习惯于将所有的业务逻辑集中放置在 `Activity` 或者 `Fragment` 中。这种方法虽然简单易懂,但在实际开发过程中会导致 UI 层和数据层耦合度过高,从而使得代码难以维护、测试困难等问题逐渐显现出来[^3]。 #### MVP 架构模式的特点 MVP(Model-View-Presenter)是一种常见的架构模式,旨在通过解耦 View 和 Model 来提高代码的可维护性和可测试性。在这种模式下,Presenter 起到了桥梁的作用,负责协调 View 和 Model 的交互过程。具体来说: - **Model**:负责处理数据操作,比如网络请求或者数据库查询。 - **View**:专注于界面展示,通常由 Activity 或 Fragment 承担。 - **Presenter**:作为核心组件,管理用户的输入事件并更新视图状态。 这种方式能够有效降低各模块之间的依赖程度,使每个部分更加独立且易于单独调试或替换[^2]。 #### MVP 架构的关键点 以下是构建基于 MVP 设计的应用所需要考虑的一些重要方面: 1. 明确职责划分:确保每一个角色只做自己该做的事情; 2. 数据传递机制:建立合理的方式让不同层次之间可以安全高效地交换信息; 3. 生命周期管理:考虑到移动设备上的特殊环境因素(如屏幕旋转),需要特别注意对象生命周期的影响; #### MVP 架构的具体实现步骤 ##### 创建新的项目 首先新建一个标准的 Android Studio 工程,并设置好基本配置选项即可开始下一步工作流程[^4]。 ##### 修改 String.xml 文件 编辑 res/values/strings.xml 添加必要的字符串资源项用于显示提示文字等内容。 ```xml <resources> <string name="app_name">My MVP App</string> <string name="hello_world">Hello world!</string> </resources> ``` ##### activity_main.xml 布局文件定义 设计简单的用户界面布局来呈现所需功能区域位置关系等基本信息。 ```xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/text_view_result" android:textSize="24sp" android:padding="16dp" android:gravity="center_horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <Button android:id="@+id/button_load_data" android:text="Load Data" android:onClick="onButtonClick" android:layout_gravity="center_horizontal" android:layout_marginTop="16dp" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout> ``` ##### 定义 Contract 接口 创建统一契约接口规范各个组成部分间相互作用方式以便后期灵活调整而不影响整体结构稳定性。 ```java public interface MainContract { interface View { void showData(String data); boolean isActive(); } interface Presenter { void loadData(); void attachView(View view); void detachView(); } } ``` ##### Model 类编写 完成具体的模型层逻辑编码任务,这里假设是从本地获取固定文本消息为例演示整个流程运作原理。 ```java public class MainModel implements MainContract.Model { @Override public String fetchData() { return "Sample Data Loaded!"; } } ``` ##### Presenter 类创建 这是连接 V(M)P 三者的纽带所在之处,承担起控制全局节奏安排的角色使命。 ```java public class MainPresenter implements MainContract.Presenter { private final MainContract.Model model; private MainContract.View view; public MainPresenter(MainContract.Model model){ this.model=model; } @Override public void loadData(){ if(view!=null && view.isActive()){ String result =model.fetchData(); view.showData(result); } } @Override public void attachView(MainContract.View view){ this.view=view; } @Override public void detachView(){ this.view=null; } } ``` ##### 在 MainActivity 文件中定义 View 功能 最后一步就是把之前准备好的所有东西组装起来形成完整的解决方案啦! ```java public class MainActivity extends AppCompatActivity implements MainContract.View{ private TextView textViewResult; private Button buttonLoadData; private MainPresenter presenter; @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initViews(); setupPresenter(); } private void initViews(){ textViewResult=findViewById(R.id.text_view_result); buttonLoadData=findViewById(R.id.button_load_data); } private void setupPresenter(){ MainModel model=new MainModel(); presenter=new MainPresenter(model); presenter.attachView(this); } public void onButtonClick(View v){ presenter.loadData(); } @Override public void showData(String data){ runOnUiThread(() ->{ textViewResult.setText(data); }); } @Override public boolean isActive(){ return !isFinishing(); } @Override protected void onDestroy(){ super.onDestroy(); presenter.detachView(); } } ``` 以上就是一个典型的 Android 应用采用 MVP 架构风格进行开发的实际案例说明文档[^1]^。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值