Android开发:一步让你代码质量提升的MVP模式

Android MVP模式基础实践指南 MVP(Model-View-Presenter)模式是一种在软件工程中广泛应用的架构模式,特别适用于Android等客户端应用的开发。它将应用分成了三个核心组件:Model(数据模型)、View(视图)和Presenter(展示器),以此来提高应用的可测试性、可维护性与可扩展性。MVP模式起源于经典的MVC(Model-View-Controller)模式,它的设计目标是为了降低View层对Model层的依赖,从而让View层更加轻量,便于测试。 阅读详情

MVP设计模式

传统的MVC(Model、View、Controller)模式,作为View层的Activity或者Fragment,通常背负的任务都非常繁重,不仅要处理View的更新,还要处理耗时的计算等操作,大大降低了代码的可阅读性,甚至有时候改代码会造成一发动全身,各种修修补补,最终导致项目臃肿难以抽离。MVP(Model、View、Presenter)模式能让代码阅读起来更加清晰,我们作为一名程序员,很有必要提升自己的代码编写质量,不仅仅给自己阅读,也要给身边的同事朋友们阅读。

MVC模式中View层不仅要对数据model处理,还要肩负View的更新,造成代码臃肿,耦合严重。

MVP模式中将View与model分离,不直接操作数据Model,让Presenter去做相应的计算、耗时操作等,而View就只做些单一的刷新View的操作,大大降低代码的耦合度,MVP模式适合于中小型项目,如果是大型的项目,可考虑用MVVM设计模式。

                                             

好了,废话不多说,多写代码才能悟道其中代码的真理,我就用最简单的例子来开展MVP模式的使用。

第一步

我们先准备两个基础的接口:

IBaseVIew.java

/**
 * @author : zzj
 * @date : 2019/1/31
 * @desp : mvp模式中的V层
 */
public interface IBaseView<T> {

}

IBasePresenter.java

/**
 * @author : zzj
 * @date : 2019/1/31
 * @desp : mvp设计模式中的P层
 */
public interface IBasePresenter<T> {

    /**
     * 关联activity或fragment
     * @param mvpView
     */
    void attachView(T mvpView);

    /**
     * activity或fragment在destroyed时与View分离
     * 避免耗时操作更新View
     */
    void detachView();
}

                              

第二步

正式使用,建立契约类,我就以排序为例子吧,建一个TestContract.java

TestContract.java

/**
 * @author : zzj
 * @date : 2019/1/31
 * @desp : 按谷歌官方推荐指定一个契约类
 */
public interface TestContract {

    interface Presenter extends IBasePresenter<MvpView>{

        void init(int[] array);

        void sort(int[] array, int sort);

    }

    interface MvpView extends IBaseView<Presenter>{

        void sortBefore(String s);

        void sortAfter(String s);

        void showToast(String msg);

    }

}

其中MvpView接口需要我们的Activity或者Fragment去实现,我们在实际开发中可自己编写MvpView的相应方法来处理我们的项目,记得就是MvpView在实现的时间我们尽量保持做View的更新,避免逻辑处理;而Presenter接口由具体的Presenter类来实现,实现具体的逻辑,如:

TestPresenter.java

/**
 * @author : zzj
 * @date : 2019/1/31
 * @desp : 测试
 */
public class TestPresenter implements TestContract.Presenter {

    public static final int SORT_SELECT = 0x01;
    public static final int SORT_INSERT = 0x02;
    private TestContract.MvpView mMvpView;

    @Override
    public void init(int[] array) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int item : array) {
            stringBuilder.append(" " + item);
        }
        if (mMvpView != null) {
            mMvpView.sortBefore("排序前:" + stringBuilder.toString());
        }
    }

    @Override
    public void sort(int[] array, int sort) {
        switch (sort) {
            case SORT_SELECT:
                array = selectSort(array);
                break;
            case SORT_INSERT:
                array = insertSort(array);
                break;
        }
        StringBuilder stringBuilder = new StringBuilder();
        for (int item : array) {
            stringBuilder.append(" " + item);
        }
        if (mMvpView != null) {
            mMvpView.showToast(sort == SORT_SELECT ? "选择排序" : "插入排序");
            mMvpView.sortAfter("排序后:" + stringBuilder.toString());
        }
    }

    /**
     * 选择排序
     */
    public int[] selectSort(int[] array) {
        for (int i = 0; i < array.length; i++) {
            int minPos = i;
            for (int j = i + 1; j < array.length; j++) {
                if (array[j] < array[minPos]) {
                    minPos = j;
                }
            }

            if (array[i] > array[minPos]) {
                int temp = array[i];
                array[i] = array[minPos];
                array[minPos] = temp;
            }

        }
        return array;
    }

    /**
     * 插入排序
     */
    public int[] insertSort(int[] array) {
        for (int i = 1; i < array.length; i++) {
            int temp = array[i];
            for (int j = i - 1; j >= 0; j--) {
                if (array[j] > temp) {
                    array[j + 1] = array[j];
                    array[j] = temp;
                }

            }
        }
        return array;
    }

    @Override
    public void attachView(TestContract.MvpView mvpView) {
        this.mMvpView = mvpView;
    }

    @Override
    public void detachView() {
        mMvpView = null;
    }

特别提醒

在实现Presenter时记得处理attachView()和detachView()方法,避免View不刷新。

 

最后一步

最后一步当然是我们的Activity实现

MainActivity.java

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity implements TestContract.MvpView {

    private TestContract.Presenter testPresenter;
    private int[] array = new int[]{6, 5, 9, 1};
    private TextView tvBefore,tvAfter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        testPresenter = new TestPresenter();
        testPresenter.attachView(this);
        tvBefore = findViewById(R.id.tv_array);
        tvAfter = findViewById(R.id.tv_sort_array);
        testPresenter.init(array);
        findViewById(R.id.btn_one).setOnClickListener(onClickListener);
        findViewById(R.id.btn_two).setOnClickListener(onClickListener);
    }

    private View.OnClickListener onClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.btn_one:
                    testPresenter.sort(array.clone(), TestPresenter.SORT_SELECT);
                    break;
                case R.id.btn_two:
                    testPresenter.sort(array.clone(), TestPresenter.SORT_INSERT);
                    break;
            }
        }
    };


    @Override
    public void showToast(String msg) {
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
    }

    @Override
    public void sortBefore(String s) {
        tvBefore.setText(s);
    }

    @Override
    public void sortAfter(String s) {
        tvAfter.setText(s);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        //在销毁的时候分离
        testPresenter.detachView();
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tv_array"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@android:color/black"
        android:textSize="16sp"
        android:text="排序前:"
        android:layout_marginBottom="20dp"
        app:layout_constraintBottom_toTopOf="@+id/tv_sort_array"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>

    <TextView
        android:id="@+id/tv_sort_array"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="50dp"
        android:text="排序后:"
        android:textColor="@android:color/black"
        android:textSize="16sp"
        app:layout_constraintBottom_toTopOf="@+id/btn_one"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

    <Button
        android:id="@+id/btn_one"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="选择排序"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btn_two"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="150dp"
        android:text="插入排序"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


</android.support.constraint.ConstraintLayout>

效果

 

附带项目传送地址

https://github.com/zhouzhijiang/MvpPrototype

 

结语

简单的介绍和演示了MVP模式的作用以及效果,在日常开发中能有效帮助我们提高自身的coding能力。欢迎大家拍砖点赞分析收藏,谢谢大家。

Google官方Android MVP模式项目示例解析 在现代软件开发中,MVP(Model-View-Presenter)设计模式已成为构建高效、可维护Android应用的首选模式之一。MVP通过分离显示逻辑与业务逻辑,提高应用程序的可测试性和可维护性。本章节将对MVP设计模式进行基础性介绍,为您深入理解其背后的设计原则和实践应用打下坚实基础。首先,MVP模式将应用架构分为三个核心组件:Model(模型)、View(视图)和Presenter(呈现器)。Model层负责处理数据和业务逻辑,与网络、数据库等数据源进行交互。 阅读详情

相关推荐

Android MVP+ViewBinding架构实战示例

在Android MVP架构中,Model层被定义为数据层,负责处理所有与数据相关的逻辑,包括数据的获取、更新、存储和管理。Model层不依赖于View层和Presenter层,保证了高内聚低耦合的模块化设计。Model层的主要作用是:- 管理数据来源:负责从网络、数据库或文件系统中获取数据。- 数据抽象:提供与数据相关的统一接口供Presenter层调用。- 数据验证:确保数据的准确性和一致性。

weixin_31938351的博客 730

android MVP——mvp架构的应用和优化

MVP架构在android还是很好用的。我也在试着将mvp用在项目中。下面我就来说说mvp模式的应用和优化。mvp模式的概念MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。比较mvc:1,在MVC里,View是可以直接访问Model的,View里会包含Model信息,不可避免的还要包括一些

boolean的博客 5925

Windows 11 + AMD 780M 运行 ComfyUI 完整指南:DirectML 实战方案

ComfyUI 是基于 PyTorch 的 Stable Diffusion 可视化工作流工具,其性能高度依赖 GPU 后端支持。在 Windows 平台,传统 CUDA 方案仅适配 NVIDIA 显卡,而 AMD 核显用户长期面临 ROCm 兼容性差、驱动链路断裂等系统级障碍。DirectML 作为微软原生机器学习 API,绕过 ROCm 生态断层,直接对接 DirectX 12 硬件抽象层,成为 RDNA 3 架构(如 Radeon 780M)在 Windows 11 上运行 AI 绘画的最优解。它提供

weixin_30099989的博客 724

Android官方TODO-MVP项目分析(上)---View 层 Presenter 层以及 Contract 分析

摘要:最近看了一下 google 官方的 sample ,做的是一个 TODO 应用,使用的是 MVP 模式,之前笔者也学习了一段时间的 MVP,前面写了几篇文章记录学习过程,也有一些思考,最后呈现出来的问题就是 Presenter 层臃肿问题,以及 View 层接口难以管理的问题。比方说 View 层,它是负责 UI 的更新工作,我们希望它里面都是 showXXXZZZ(@Nullable Par

范二er 2392

Ubuntu22.04安装ROS1

代表使用 2 线程进行编译,可以根据 CPU 适当调整。如果出现小乌龟窗口,说明安装成功 🎉!启动成功,则打开另一个终端,测试。需要解决一些兼容性问题,因为。由于 Ubuntu 22.04。过程,确保成功安装。

asafriend的博客 4644

别再浪费主板上的PCIE插槽了!手把手教你用VL805芯片打造高速USB3.0扩展坞

本文详细介绍了如何利用VL805芯片将主板闲置的PCIE插槽改造为高性能USB3.0扩展坞。从芯片选型、电路设计到焊接工艺和系统调试,提供了一套完整的实战指南,帮助用户充分释放硬件潜能,实现高达5Gbps的传输速度。

weixin_27134495的博客 326

Android Mvp架构设计与性能优化

Android Mvp架构设计与性能优化 什么是mvp架构设计? MVP是模型(Model)、视图(View)、主持人(Presenter)的缩写,分别代表项目中3个不同的模块。   模型(Model):负责处理数据的加载或者存储,比如从网络或本地数据库获取数据等;   视图(View):负责界面数据的展示,与用户进行交互;   主持人(Presenter):相当于协调者,是模型与视

LiuRenyou的博客 1512

全网最全的AItium Designer 16下载资源与安装步骤

Altium Designer 除了全面继承包括Protel 99SE、Protel DXP在内的先前一系列版本的功能和优点外,还增加了许多改进和很多高端功能。该平台拓宽了板级设计的传统界面,全面集成了FPGA设计功能和SOPC设计实现功能,从而允许工程设计人员能将系统设计中的FPGA与PCB设计及嵌入式设计集成在一起。...

WQ的博客 1万+

MVP模式在Android实际项目中的应用和优化

注:本文阅读需要对MVP模式有基本了解。 MVP模式已经出现有很长一段时间了,但是火起来是这两年的事情。 关于MVP的概览,介绍,乃至于教程,Demo,实例,网上都有很多,我也有一篇文章专门收录了一些关于MVP的资料,起码现在很多朋友对表现层(Presenter),视图层(View),模型协议类,接口这些词并不陌生了。 很长一段时间,出去面试的筒子们经常会被问到一个问题:知道谷歌四件套么?(MVP...

weixin_30383279的博客 245

QT实现HTTP文件(夹)下载的完整流程与实战技巧

本文详细介绍了使用QT框架实现HTTP文件和文件夹下载的完整流程与实战技巧。通过QNetworkAccessManager等核心类,讲解了从单文件下载、大文件处理、进度显示、暂停/取消功能,到复杂的文件夹下载策略。文章重点剖析了断点续传、错误处理与网络健壮性等关键问题,为C++桌面应用集成稳定高效的下载功能提供了专业指导。

weixin_29239279的博客 277

DeepSeek如何构建可扩展的 AI 驱动交易系统,基于 MetaTrader 5 与 Python 利用先进的数据处理、机器学习和容器化部署来优化算法交易。

MT5 Python API 架构设计分为三层:通信层:利用异步消息传递(例如 ZeroMQ 或标准套接字编程)支持每秒数万个数据请求。转换层: C++ 动态库有效地将 MT5 命令转换为 Python 对象(反之亦然),从而优化速度和内存使用率。接口层:提供Pythonic API,封装了所有终端功能,包括:1)实时价格订阅(滴答或秒级更新)2)历史数据检索(从M1到更高的时间范围)3)订单流监控(交易详情和市场深度)4)策略执行引擎(用于算法交易)

iCloudEnd的博客 1380

Android 浅谈Mvp模式

一、概述对于MVP(Model View Presenter),大家都知道是为了让Model和View完全解耦,MVC的演化版本等等。既然有这样的好处,那么就很适合于用于团队开,各自模块负责,互不干扰。相信大家对于MVC臃肿的Activity肯定看起来恶心,特别是对于项目的主Activity,如果每个人都要写几行代码,那么到了项目后期,完全是有可能随意间的一个小动作,就让整个团队加班找BUG啊。不管

Vension-代码搬运工 716

第18章:Ingestion Pipeline 数据摄取流水线

本文介绍了LlamaIndex的IngestionPipeline如何解决合同文档处理中的四大核心问题:不可重复、无追溯、无容错和无法缓存。通过标准化数据处理流程,将手工操作升级为工厂流水线模式,实现数据的可复用、可追踪和高效处理。文章详细阐述了Pipeline的设计原理,包括Transformation的串行编排、缓存机制(基于输入和Transformation的哈希值)以及数据血缘追踪(通过Node的metadata记录处理过程)。

davidwang456的专栏 62

Android App整体架构设计的思考

架构设计的目的对程序进行架构设计的原因,归根到底是为了提高生产力。通过设计使程序模块化,做到模块内部的高聚合和模块之间的低耦合。

娶个杀手做老婆 476

uni-app:实现APP设置手机闹钟+取消闹钟+响铃重复/文字等,帮用户设置好闹钟并备注文本,uni-app设置安卓系统闹钟和苹果ios系统闹钟(uniapp调用手机上的闹钟,详细示例代码demo)

uniapp设置安卓和iOS闹钟的插件,uni-app设置安卓系统闹钟,uniapp设置苹果ios系统闹钟,uniapp设置定时闹铃的完整解决方案,UniApp设置手机闹钟,uniApp如何设置手机闹铃,uniapp设置闹钟,设置闹钟提醒,uni-app设置安卓系统闹钟_通过uniapp设置原声闹钟,调用android系统闹钟,如何在App中启动系统闹钟,uniapp如何取消闹钟,通过调用ios的原生接口来设置手机闹钟,uni-app 调用手机闹钟功能,uniap调用ios系统闹钟,uniapp调用手机上的

✅ 精选推荐文章 4233

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

关于Android App整体架构的设计

本文是对我在知乎一个回答的整理,其中的内容大多是对我平时的阅读和实践的总结,希望对Android的开发者有所帮助。但毕竟是个人的一些思考,难免有疏漏,也欢迎对本文的内容提出建议。 1. 架构设计的目的         对程序进行架构设计的原因,归根到底是为了提高生产力。通过设计使程序模块化,做到模块内部的高聚合和模块之间的低耦合。这样做的好处是使得程序在开发的过程中,开发人员只需要专注

Jason_Wang的博客 1664

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Android 之MVP模式

前言:如果童鞋对于接口回调,多态,泛型(这个很重要)不是特别熟练,或者不是特别了解,建议还是不要使用这种模式。先谢谢常规MVP练练手,等真正对这些知识能熟练掌握了再来学习MVP模式。这个架构用到了大量的接口,泛型。(基础很重要啊)使用MVP模式架构项目也有2个了。最新的项目原本想结合Dagger2去做(听说会让结构更加清晰)。不过在看了一上午Dagger2以后,我决定下个项目再集成,先把现有的MVP

sunxiaogang0214的博客 1101

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

探索Android开发新模式:MVP入门实践

探索Android开发新模式:MVP入门实践 在快速迭代的移动应用领域,设计模式对于构建可维护、可扩展的软件至关重要。今天,我们聚焦于一个专为简化Model-View-Presenter(MVP)理解而设的开源宝藏——《Android MVP Sample Application》。无论你是初涉Android领域的新人,还是寻求代码优化的老手,这款应用都值得一探究竟。 项目介绍 《Android ...

gitblog_00028的博客 437

EasyGank:基于RxJava和MVP模式的Android开发框架完全指南

EasyGank是一个基于RxJava系列和MVP模式构建的Android开发框架,旨在帮助开发者快速构建高质量的Android应用。本指南将带你全面了解这个强大框架的核心功能、架构设计和使用方法,让你轻松掌握现代Android开发的最佳实践。 ## 为什么选择EasyGank框架? 在Android开发中,选择合适的架构模式和技术栈至关重要。EasyGank框架结合了RxJava和MVP模式

gitblog_00458的博客 823

android-kotlin-mvp-architecture单元测试实践:提升代码质量的关键5个步骤

android-kotlin-mvp-architecture是一个基于Kotlin语言实现MVP架构的Android示例项目,集成了Dagger2、Room、RxJava2等主流框架。本文将分享如何在该项目中实施单元测试,帮助开发者构建更健壮的应用。 ## 1. 单元测试环境配置与依赖 项目的测试依赖已在`app/build.gradle`中预设,主要包括JUnit和Mockito两大核心库

gitblog_00531的博客 884

android 之MVP模式的入门

android 之MVP模式的入门

zhouguizhi 721

Android 开发中的架构模式 -- MVC / MVP / MVVM

详细解读 Android 开发中常用的架构模式,MVC / MVP / MVVM 看完本文可以达到: 了解如何分析一个架构模式 掌握 MVC,MVP,MVVM 架构定义和实现 适合人群:对 MVC / MVP / MVVM 感兴趣或者有混淆的同学们...

GitChat 591

探索惊奇:一款基于MVP模式的Android漫威应用

探索惊奇:一款基于MVP模式的Android漫威应用 项目介绍 欢迎来到Marvel Application,一个专为漫威粉丝打造的Android客户端,它将为你展示来自Marvel.com的精彩内容。这个项目由Mohsen Mirhoseini开发,并在smava GmbH的技术评估中脱颖而出。不仅如此,该项目还被用作一系列技术教程和文章的示例代码库。 项目技术分析 这款应用采用的是先进的开...

gitblog_00078的博客 1001

MVP 模式深度解析:View、Presenter、Interactor 在 Android Studio MVP 模板中如何分工协作

**Android Studio MVP 模板**是一款专为 Android Studio 打造的 MVP 模式(Model-View-Presenter)代码模板,它能让新手一键生成结构规范的 View、Presenter、Interactor 三层代码,从此告别手写样板代码。本文将深入剖析这三个角色在模板中如何分工协作,并教你快速上手这套模板。 ## 一、为什么需要 Android Stud

gitblog_01048的博客 668

如何基于EasyGank框架快速开发你自己的Android应用:MVP+RxJava的终极指南

想要快速构建高质量的Android应用吗?EasyGank框架为你提供了一个完整的解决方案!这是一个基于MVP架构模式和RxJava系列技术的Android项目构建框架,能够帮助你高效开发现代化的Android应用。💡 ## 什么是EasyGank框架? **EasyGank**是一个功能强大的Android开发框架,它集成了当前最流行的技术栈:**MVP模式**、**RxJava**、**

gitblog_00485的博客 680

探索高效开发新维度:MvpFrame - 一个强大的Android MVP框架

探索高效开发新维度:MvpFrame - 一个强大的Android MVP框架 在移动应用开发领域,尤其是Android平台,选择一个合适的框架可以帮助开发者提高效率,减少错误并保持代码的可维护性。今天我们要向您推荐的是,这是一个精心设计的Android MVP(Model-View-Presenter)框架,旨在优化您的开发流程。 项目简介 MvpFrame是一个基于anko库构建的轻量级框架,...

gitblog_00089的博客 591
上一篇: 解决适配Android9.0时出现相关v4/v7依赖报错的问题
下一篇: 热修复:关于Tinker在Android9.0机器上合成失败的解决方案
JosonChou
博客等级 码龄11年 8粉丝 18原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值