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

ArcGIS实战:地形湿度指数(TWI)计算全流程解析

本文详细解析了ArcGIS中地形湿度指数(TWI)的计算全流程,从DEM数据获取、填洼处理到水流方向与汇流累积量计算,最终实现TWI的精准计算。通过实战步骤指导,帮助读者掌握水文建模和土壤湿度预测的关键技术,适用于农业规划、生态研究等领域。

weixin_29231725的博客 869

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

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

范二er 2392

工程师必看:如何用MINITAB快速计算传感器寿命(附详细步骤)

本文为工程师提供了使用MINITAB软件快速计算传感器寿命的详细实战指南。文章重点阐述了如何通过数据预处理、回归分析拟合阿伦尼斯模型,并最终预测平均寿命与置信区间,帮助工程师高效处理加速寿命试验数据,提升可靠性分析工作的准确性与效率。

weixin_29296241的博客 248

【ERROR】ERROR1: PROJ: proj_create_from_database: Cannot find proj.db - 环境变量配置与路径修复指南

本文详细解析了地理空间数据处理中常见的【ERROR】ERROR1: PROJ: proj_create_from_database: Cannot find proj.db 错误。该错误的根源是PROJ库无法定位其核心数据文件proj.db。文章提供了从问题诊断到修复的完整指南,包括如何在不同系统(Windows/macOS/Linux)和安装方式(Conda/pip/源码编译)下找到正确的proj.db文件路径,并通过设置PROJ_LIB环境变量(临时、代码内或永久)彻底解决问题,同时给出了进阶排查技巧和

m2n3o4p5的博客 557

Android Mvp架构设计与性能优化

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

LiuRenyou的博客 1512

瑞萨芯片串口配置,基于RL78芯片的串口使用配置

在这里隆重给大家介绍瑞萨编辑器CS+ for CA 的自动生成代码功能,只需要配置几个参数,就可以得到你想要的串口配置了,我现在已经忘记怎么手动配置寄存器了,哈哈。选择设置,此时将端口设置成功接下来设置时钟,根据自己的芯片所需设置相应的时钟,自己芯片是什么时钟查看数据手册和原理图可以找到。瑞萨芯片的串口配置其实和ST芯片的串口配置差不多,只是ST芯片的中文数据手册比较多,就更好配置了,找到所需要的串口配置IO口,此时将UART0 配置为引脚P61和P62,瑞萨芯片的串口配置竟然要配置串口。

qq_45315904的博客 4302

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

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

weixin_30383279的博客 245

ComfyUI安装包运行前准备:增加虚拟内存

在Windows系统中,虚拟内存是一种重要的系统资源管理机制,它主要通过将硬盘空间用作内存来扩展系统的可用内存容量。以下是虚拟内存的主要作用: 1. 扩展物理内存容量 当物理内存(RAM)不足时,系统会将一部分数据从内存转移到硬盘上的虚拟内存区域(也称为“分页文件”或“交换文件”)。这样可以为正在运行的程序提供额外的“内存空间”,确保系统能够继续运行,而不会因为内存不足而崩溃。 2. 提高系统稳定性 虚拟内存为系统提供了一个缓冲区。如果没有虚拟内存...

聚梦小课堂 1万+

服务器取证——服务器基础知识

服务器基础知识

记录并分享学习安全的知识点.. 2481

Android 浅谈Mvp模式

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

Vension-代码搬运工 716

欺诈文本分类微调(一):基座模型选型

通义千问Qwen2具有0.5B、1.5B、7B、72B等一系列参数大小不等的模型,我们需要做的是从大到小依次测试每个模型的能力,找到满足自己需要的最小参数模型。依1.5B和1.5B-Instruct的主要区别:按照官方文档,前者是预训练模型,后者是经过指令微调的模型。

golfxiao的专栏 2655

Android App整体架构设计的思考

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

娶个杀手做老婆 476

31、工程中不确定性量化与优化的全面解析

本文全面解析了工程中不确定性量化与优化的关键方法。针对数据充足与不足两种情况,分别介绍了概率理论和非概率方法在不确定性建模中的应用;系统阐述了采样方法、FORM/SORM、泰勒级数近似等不确定性传播技术;深入比较了RBDO与RDO两种主流优化框架的原理、步骤及适用场景,并通过两杆桁架案例展示了具体实现过程。文章旨在为工程师提供一套完整的从不确定性分析到优化设计的方法论,提升工程系统的可靠性与稳健性。

php55的博客 121

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

关于Android App整体架构的设计

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

Jason_Wang的博客 1664

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Android 之MVP模式

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

sunxiaogang0214的博客 1101

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

探索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、付费专栏及课程。

余额充值