Android系统架构之MVP使用

简介: Android系统架构之MVP使用在开始这篇博客之前,我们先来探讨几个问题:为什么要用MVP?传统开发中,View(包括Activity、Fragment及其子类)作为APP功能的基本单元完成了过多任务,包括UI绘制与刷新、页面逻辑、动画渲染,这就导致一些复杂的页面动辄数千行,这就导致维护和升级的成本越来越高,代码牵一发而动全身。

Android系统架构之MVP使用
在开始这篇博客之前,我们先来探讨几个问题:

  1. 为什么要用MVP?
    传统开发中,View(包括Activity、Fragment及其子类)作为APP功能的基本单元完成了过多任务,包括UI绘制与刷新、页面逻辑、动画渲染,这就导致一些复杂的页面动辄数千行,这就导致维护和升级的成本越来越高,代码牵一发而动全身。为了解决这个问题,我们提出了MVP的思想。
  2. MVP如何解决这个View代码过于庞大的问题?
    MVP全称是Model,View,Presenter,核心思想就是将整个应用分为三层。
  3. View层:视图层,包含界面相关功能,主要提供与用户的交互,包括实现设计师要求的界面以及动画的加载等交互效果。View层一般会持有Presenter的引用,通过这个引用将一些业务逻辑委托给Presenter完成,或者也可以通过依赖注入(如Dagger)的方式获得Presenter的实例进而实现逻辑操作的委托;
  4. Presenter层:逻辑控制层,这层是从View层中通过抽离控制逻辑部分形成的,充当View层和Model层交互的中间人,比如用户在屏幕上点击了下载按钮,下载一张图片并显示出来,这时,View层会发出网络请求,而Presenter层会接受View层的请求,并分发给对应的Model处理,最终结果通过Presenter层反馈给View层并显示出来;
  5. Model层:封装各种数据来源,例如远程网络数据,本地数据库数据,对Presenter层提供简单的接口。
  6. MVP与MVC的区别
    MVP作为经典MVC的延伸,与MVC最大的区别在于:MVP中的View层和Model层没有直接通信,是通过Presenter这个中间人进行的,其交互都是基于接口的,并且通常情况下,Presenter和View是一对一的,特殊情况下可能存在一个View对应多个Presenter的情况;而MVC中View和Model是直接通信的,Control本身是基于行为的,可以被多个View共享,比如网络下载行为。

OK,现在我们正式开始实现我们自己的MVP框架。

一、 创建callback接口,Callback 接口是Model层给Presenter层反馈请求信息的传递载体,所以需要在Callback中定义数据请求的各种反馈状态:

public interface MvpCallback {

   /**
     * 数据请求成功
     * @param data 请求到的数据
     */
    void onSuccess(String data);
    /**
     *  使用网络API接口请求方式时,虽然已经请求成功但是由于某些原因无法正常返回数据。
     * @param msg:无法返回数据的原因
     */
    void onFailure(String msg);
     /**
     * 请求数据失败,指在请求网络API接口请求方式时,出现无法联网、缺少权限,内存泄露等原因导致无法连接到请求数据源。
     */
    void onError();
    /**
     * 当请求数据结束时,无论请求结果是成功,失败或是抛出异常都会执行此方法给用户做处理,通常做网络请求时可以在此处隐藏“正在加载”的等待控件
     */
    void onComplete();

}

二、 创建Model类,Model 类中定了具体的网络请求操作。为模拟真实的网络请求,利用postDelayed方法模拟耗时操作,通过判断请求参数反馈不同的请求状态:

public class MvpModel {

    /**
     * 获取网络接口数据
     * @param param 请求参数
     * @param callback 数据回调接口
     */
    public static void getNetData(final String param, final MvpCallback callback){
        // 利用postDelayed方法模拟网络请求数据的耗时操作
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                switch (param){
                    case "normal":
                        callback.onSuccess("根据参数"+param+"的请求网络数据成功");
                        break;
                    case "failure":
                        callback.onFailure("请求失败:参数有误");
                        break;
                    case "error":
                        callback.onError();
                        break;
                }
                callback.onComplete();
            }
        },2000);
    }

}

三、 创建View接口,View接口是Activity与Presenter层的中间层,它的作用是根据具体业务的需要,为Presenter提供调用Activity中具体UI逻辑操作的方法。

public interface MvpView {

    /**
     * 显示正在加载进度框
     */
    void showLoading();
    /**
     * 隐藏正在加载进度框
     */
    void hideLoading();
    /**
     * 当数据请求成功后,调用此接口显示数据
     * @param data 数据源
     */
    void showData(String data);
    /**
     * 当数据请求失败后,调用此接口提示
     * @param msg 失败原因
     */
    void showFailureMessage(String msg);
    /**
     * 当数据请求异常,调用此接口提示
     */
    void showErrorMessage();

}

四、 创建Presenter类,Presenter类是具体的逻辑业务处理类,该类为纯Java类,不包含任何Android API,负责请求数据,并对数据请求的反馈进行处理。Presenter类的构造方法中有一个View接口的参数,是为了能够通过View接口通知Activity进行更新界面等操作。

public class MvpPresenter {

    // View接口
    private MvpView mView;
    public MvpPresenter(MvpView view){
        this.mView = view;
    }
    /**
     * 获取网络数据
     * @param params 参数
     */
    public void getData(String params){
        //显示正在加载进度条
        mView.showLoading();
        // 调用Model请求数据
        MvpModel.getNetData(params, new MvpCallback() {
            @Override
            public void onSuccess(String data) {
                //调用view接口显示数据
                mView.showData(data);
            }
            @Override
            public void onFailure(String msg) {
                //调用view接口提示失败信息
                mView.showFailureMessage(msg);
            }
            @Override
            public void onError() {
                //调用view接口提示请求异常
                mView.showErrorMessage();
            }
            @Override
            public void onComplete() {
                // 隐藏正在加载进度条
                mView.hideLoading();
            }
        });
    }

}

五、 页面布局,只需要包括三个按钮即可,就是对应于访问成功,失败,异常三种情况的按钮

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    android:orientation="vertical"
    tools:context="com.jessewu.mvpdemo.MainActivity">
    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:text="点击按钮获取网络数据"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="获取数据【成功】"
        android:onClick="getData"
        />
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="获取数据【失败】"
        android:onClick="getDataForFailure"
        />
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="获取数据【异常】"
        android:onClick="getDataForError"
        />

六、创建MainActivity,通过按钮点击进行调用

public class MainActivity extends AppCompatActivity implements MvpView {

    //进度条
    ProgressDialog progressDialog;
    TextView text;
    MvpPresenter presenter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        text = (TextView)findViewById(R.id.text);
        // 初始化进度条
        progressDialog = new ProgressDialog(this);
        progressDialog.setCancelable(false);
        progressDialog.setMessage("正在加载数据");
        //初始化Presenter
        presenter = new MvpPresenter(this);
    }
    // button 点击事件调用方法
    public void getData(View view){
        presenter.getData("normal");
    }
    // button 点击事件调用方法
    public void getDataForFailure(View view){
        presenter.getData("failure");
    }
    // button 点击事件调用方法
    public void getDataForError(View view){
        presenter.getData("error");
    }
    @Override
    public void showLoading() {
        if (!progressDialog.isShowing()) {
            progressDialog.show();
        }
    }
    @Override
    public void hideLoading() {
        if (progressDialog.isShowing()) {
            progressDialog.dismiss();
        }
    }
    @Override
    public void showData(String data) {
        text.setText(data);
    }
    @Override
    public void showFailureMessage(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
        text.setText(msg);
    }
    @Override
    public void showErrorMessage() {
        Toast.makeText(this, "网络请求数据出现异常", Toast.LENGTH_SHORT).show();
        text.setText("网络请求数据出现异常");
    }
}

分析一下代码,这里的View对应的就是我代码中的MainActivity,Model对应我代码中的MvpModel类,Presenter对应我代码中的MvpPresenter类。代码原理就是,在MainActivity中持有一个MvpPresenter类的实例presenter,用户与MainActivity进行交互(准确的说应该是与MainActivity对应的页面交互),用户的网络请求将会委托给presenter中的getData()方法,而在getData()中再将网络数据请求操作委托给MvpModel中的静态方法getNetData()进行实现,因为是公有静态,所以这里不需要持有Model的引用,同时通过View接口实现对页面的更新,这个View接口是在MainActivity中实现的。

从整体上看,MVP其实首先就是通过面向对象技术将一个页面及其完整的交互逻辑封装为三部分,分别是Model, View和Presenter, 三者之间通过接口进行交互,Model与Present二者完全解耦,二者通过Presenter实现交互,而在Presenter中在通过一种多态实现页面刷新接口中方法,这个方法的实现在View中。

作者:kuai_j
来源:CSDN
原文:https://blog.csdn.net/qq_41613281/article/details/90449133
版权声明:本文为博主原创文章,转载请附上博文链接!

相关文章
|
17天前
|
存储 设计模式 数据库
构建高效的安卓应用:探究Android Jetpack架构组件
【4月更文挑战第20天】 在移动开发的世界中,构建一个既高效又可维护的安卓应用是每个开发者追求的目标。随着Android Jetpack的推出,Google为开发者提供了一套高质量的库、工具和指南,以简化应用程序开发流程。本文将深入探讨Jetpack的核心组件之一——架构组件,并展示如何将其应用于实际项目中,以提升应用的响应性和稳定性。我们将通过分析这些组件的设计原则,以及它们如何协同工作,来揭示它们对于构建现代化安卓应用的重要性。
|
2月前
|
数据库 Android开发 开发者
构建高性能微服务架构:从理论到实践构建高效Android应用:探究Kotlin协程的优势
【2月更文挑战第16天】 在当今快速迭代和竞争激烈的软件市场中,微服务架构以其灵活性、可扩展性和独立部署能力而受到企业的青睐。本文将深入探讨如何构建一个高性能的微服务系统,涵盖从理论基础到具体实现的各个方面。我们将重点讨论服务拆分策略、通信机制、数据一致性以及性能优化等关键主题,为读者提供一个清晰、实用的指南,以便在复杂多变的业务环境中构建和维护健壮的微服务体系结构。 【2月更文挑战第16天】 在移动开发领域,性能优化和流畅的用户体验是至关重要的。随着技术的不断进步,Kotlin作为一种现代编程语言,在Android开发中被广泛采用,尤其是其协程特性为异步编程带来了革命性的改进。本文旨在深入
|
4月前
|
XML 前端开发 测试技术
Android基础知识:解释Android的MVC和MVP模式。
Android基础知识:解释Android的MVC和MVP模式。
32 0
|
2天前
|
存储 前端开发 Java
Android应用开发中的MVP架构模式实践
【5月更文挑战第5天】随着移动应用开发的复杂性增加,传统的MVC(Model-View-Controller)架构在应对大型项目时显得笨重且不灵活。本文将探讨一种更适应现代Android应用开发的架构模式——MVP(Model-View-Presenter),并展示如何在Android项目中实现该模式以提升代码的可维护性和可测试性。通过对比分析MVP与传统MVC的差异,以及提供一个实际案例,读者将能深入了解MVP的优势和实施步骤。
|
7天前
|
前端开发 测试技术 数据处理
安卓开发中的MVP架构模式深度解析
【4月更文挑战第30天】在移动应用开发领域,模型-视图-呈现器(Model-View-Presenter, MVP)是一种广泛采用的架构模式。它旨在通过解耦组件间的直接交互来提高代码的可维护性和可测试性。本文将深入探讨MVP在安卓开发中的应用,揭示其如何促进代码的模块化,提升用户界面的响应性,并简化单元测试过程。我们将从理论概念出发,逐步过渡到实践案例,为读者提供一套行之有效的MVP实施策略。
|
14天前
|
传感器 Java Android开发
Android HAL深入探索(1): 架构概述
Android HAL深入探索(1): 架构概述
25 1
|
16天前
|
设计模式 前端开发 数据库
构建高效Android应用:使用Jetpack架构组件实现MVVM模式
【4月更文挑战第21天】 在移动开发领域,构建一个既健壮又易于维护的Android应用是每个开发者的目标。随着项目复杂度的增加,传统的MVP或MVC架构往往难以应对快速变化的市场需求和复杂的业务逻辑。本文将探讨如何利用Android Jetpack中的架构组件来实施MVVM(Model-View-ViewModel)设计模式,旨在提供一个更加模块化、可测试且易于管理的代码结构。通过具体案例分析,我们将展示如何使用LiveData, ViewModel, 和Repository来实现界面与业务逻辑的分离,以及如何利用Room数据库进行持久化存储。最终,你将获得一个响应迅速、可扩展且符合现代软件工
19 0
|
24天前
|
XML 前端开发 测试技术
安卓架构模式:MVC、MVP、MVVM及更多
【4月更文挑战第13天】本文探讨了安卓应用开发中的常见架构模式,包括MVC、MVP和MVVM,以及VIPER和Clean Architecture。MVC分离关注点,易于理解,但安卓不直接支持。MVP通过呈现器实现更清晰的分层和便于单元测试。MVVM利用数据绑定简化UI逻辑,适合声明式编程。开发者应根据项目需求、团队技能和维护周期选择合适架构,随着工具和框架的进步,未来将提供更多模块化、可测试性和敏捷性的解决方案。
|
25天前
|
存储 数据库 Android开发
构建高效安卓应用:采用Jetpack架构组件优化用户体验
【4月更文挑战第12天】 在当今快速发展的数字时代,Android 应用程序的流畅性与响应速度对用户满意度至关重要。为提高应用性能并降低维护成本,开发者需寻求先进的技术解决方案。本文将探讨如何利用 Android Jetpack 中的架构组件 — 如 LiveData、ViewModel 和 Room — 来构建高质量的安卓应用。通过具体实施案例分析,我们将展示这些组件如何协同工作以实现数据持久化、界面与逻辑分离,以及确保数据的即时更新,从而优化用户体验并提升应用的可维护性和可测试性。
|
28天前
|
存储 设计模式 前端开发
构建高效安卓应用:Jetpack MVVM 架构的实践之路
【4月更文挑战第9天】 在移动开发的迅猛浪潮中,Android 平台以其开放性和灵活性受到开发者青睐。然而,随着应用复杂度的不断增加,传统的开发模式已难以满足快速迭代和高质量代码的双重要求。本文将深入探讨 Jetpack MVVM 架构模式在 Android 开发中的应用实践,揭示如何通过组件化和架构设计原则提升应用性能,实现数据驱动和UI分离,进而提高代码可维护性与测试性。我们将从理论出发,结合具体案例,逐步展开对 Jetpack MVVM 架构的全面剖析,为开发者提供一条清晰、高效的技术实施路径。