Android Mvvm设计模式的详解与实战教程

news2024/11/14 2:20:37

一、介绍

        在开发设计模式中,模式经历了多次迭代,从MVC到MVP,再到如今的MVVM。发现的过程其实很简单,就是为了项目更好的管理。

        设计模式严格来说属于软件工程的范畴,但是如今在各大面试中或者开发中,设计模式被问的很多。特别是八股文的二十三种设计模式,可分三大类:行为型、结构型、创建型。

二、模式介绍

        模式的设计更多的体现在管理与架构能力,即使在项目中,你不用任何设计模式,代码也可以正常的跑起来,但是通过模式设计以后,在项目管理与质量控制,以及解耦等场景特别方便。

        任何设计模式和手段都是为了项目的更好管理,这种模式更像一种流程。从技术角度来分析,不能作为衡量一个人的技术好坏,但是可以作为参考,来判断一个人的综合能力以及设计、架构能力。

了解设计模式,可以提高一个人的综合能力。

三、MVMM详解与设计

MVVM是什么

        目前在做有UI展示的一些项目或者端,都在说MVVM设计模式。MVVM全程view-viewModel-Model。还是分为三层,View层,viewModel:view与业务层,Model数据业务层

View:是我们fragment或者Activity界面,主要处理UI渲染和交互的

viewModel:介于view与Module之前,处理数据与逻辑上的,将Model请求的结果返回给view层

Model:与viewModel打交道,将view需要的数据通过Model层来请求,然后将请求到的结果返回给viewModel。

Mvvm流程

        在Mvvm设计模式中,view主要就是做数据与UI的绑定,常见的View与Model没有直接交互,需要申明都是通过ViewModel进行交互的。ViewModel从名字就可以看出,是View与Model的拼写,所以肯定是与View和Moel有关,在MVVM中,ViewModel的核心作用就是作为View与Model的桥梁,将View的需求告诉Model,然后从Model中将结果拿到,处理好给View,View进行渲染。

Mvvm的助手databinding:

        通过Google官方我们也了解到,MVVM的推波导致了DataBinding的被很好的推广,在Mvvm中,View中的绑定和页面的view是通过Databinding来完成,很多开发者可能还没体验过DataBinding,甚至也没有使用过,这个也不影响到Mvvm的使用,因为DataBinding只负责View与Data的绑定,即使你不会可以手动处理。

如果想了解DataBinding的小伙伴,可以看博主一下的文档:

Android databinding的接入使用与详解(一)_android databinding使用_蜗牛、Z的博客-CSDN博客

Android databinding之RecycleView使用与讲解(二)_android databinding recyclerview_蜗牛、Z的博客-CSDN博客

Android databinding之数据单向与双向绑定详解与使用(三)_databinding双向绑定_蜗牛、Z的博客-CSDN博客

Android databinding之BindingAdapter与BindingConversion详解与使用(四)_蜗牛、Z的博客-CSDN博客

Android databinding之BindingMethod与BindingMethods介绍与使用(五)_android开发bindingmethods的使用_蜗牛、Z的博客-CSDN博客

Android DataBinding之布局include 和 viewStub详解与使用(六)_databinding viewstub_蜗牛、Z的博客-CSDN博客

Android DataBinding之布局中(layout)事件、运算逻辑、资源、工具类的使用与详解(七)_databinding layout_蜗牛、Z的博客-CSDN博客

新手礼包:

        这几篇文档基本都是从零开始学databinding的文章,只要你跟着看,慢慢实践里面的dmeo,都是没问题的。以上新手礼包可以帮你很好的处理Mvvm中数据的绑定

数据传递MutableLiveData:

通过以上知道ViewModel与View进行数据交互,他们之间如何传递数据?在viewmodel中提供了

MutableLiveData,它继承了LiveData,类似事件订阅,你发送了数据,在view中订阅即可,数据将会回传到订阅处。LiveData也支持生命周期的绑定,防止数据订阅中,当前页面销毁,数据还在订阅,导致页面发生内存泄露。

四、实战

        通过以上的学习,我们大概了解了Mvvm包括哪些?如何架构和搭建MVVM。通过关键模块的处理我们将继续学习实战。

Model模块

model主要是数据处理,在搭建代码的时候,我们最好有良好的编程风格,可以先搭建一个基础、抽象类,后面的model都继承直接使用,即使是空类也要写一个,方便以后扩展。

open abstract class BaseModel {
}
//一般梳理数据类比较多
class MyModel : BaseModel() {

    //网络数据的获取


    //数据库的操作


    //本地的数据缓存:添加与删除

    public fun getInitData():String{
        return "init data that info"
    }


}

Model的是和数据打交道,处理好,我们就可以处理搭建ViewModel了

ViewModel层:

ViewModel层夹在View与model之间,是逻辑的中转,view要什么找ViewModel,model通过ViewModel把数据传递给View。

ViewModel这里面主要有两块:搭建和创建

搭建

搭建需要继承public AndroidViewModel(@NonNull Application application),由于ViewModel需要与View合作,所以还需要了解当前的对象生命周期防止内存泄露等发生。

这里需要使用到接口:LifecycleObserver

LifecycleObserver用法:

直接继承,然后通过状态绑定对应的方法,当lifecycle绑定完就可以分发生命周期状态

  @OnLifecycleEvent(Lifecycle.Event.ON_START)
    public fun onstart(){
        log("onstart")
    }
1、生命状态回调

//定义了页面监听生命周期监听
interface BaseViewModelLifecycleObserver : LifecycleObserver {

    companion object{
        const val TAG="life"
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    public fun onstart(){
        log("onstart")
    }


    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    public fun onStop() {
        log("onStop")
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public fun onResume() {
        log("onResume")
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public fun onPause() {
        log("onPause")
    }


    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    public fun ondestory() {

        log("ondestory")
    }


    public fun log(msg:String)
    {
        Log.e(TAG,"${msg}")
    }
}
2、BaseViewModel
abstract open class BaseViewModel(val context: Application) : AndroidViewModel(context),
    BaseViewModelLifecycleObserver {

}
3、定义业务的ViewModel
class MyViewModel(context: Application) : BaseViewModel(context) {


    private val model: MyModel by lazy { MyModel() }

    public val initLiveData: MutableLiveData<String> by lazy { MutableLiveData() }


    public fun showToast(msg: String) {
        Toast.makeText(getApplication(), msg, Toast.LENGTH_SHORT).show()

    }

    public fun initData() {
        val data=model.getInitData()
        initLiveData.value=data
    }


}

这里面多了一个MutableLiveData,就是数据回传的订阅,ViewModel发送了数据给View通过LiveData进行订阅。在这里面要创建Model对象

创建

创建这里面涉及到了kotlin的泛型问题,相比Java,kotlin的泛型比较复杂,由于创建是和DataBinding绑在一起的,这边先介绍泛型的创建与生命周期的绑定

    val type = javaClass.genericSuperclass
        if (type != null && type is ParameterizedType) {
            val actualTypeArguments = type.actualTypeArguments
            val tClass = actualTypeArguments[1]
viewModel= AndroidViewModelFactory.getInstance(application).create(tClass as Class<V>)
        }


        lifecycle.addObserver(viewModel)

    lifecycle.addObserver(viewModel):绑定了当前的生命周期

注意:在需要消费,否则导致内存泄露

    override fun onDestroy() {
        super.onDestroy()
        lifecycle.removeObserver(viewModel)
    }

View模块

View模块主要就是DataBinding的创建与ViewMOdel的创建,ViewModel上面已介绍如何创建,下面将介绍如何去架构这个基础页面,去管理

这边架构的页面分为两个类:第一个是DataBinding类,还有一个是DataBinding与ViewModel继承类,为什么要分开?因为在正常业务中,有些模块不需要ViewModel,但是DataBinding是必须使用,所以只需要继承DataBinding类即可。

DataBinding基础类:
 

open abstract class BaseDataBindModelActivity<T : ViewDataBinding>() : FragmentActivity() {

    public lateinit var binding: T

    //配置当前页面布局资源
    @LayoutRes
    public abstract fun getLayoutResId(): Int

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = DataBindingUtil.setContentView<T>(this, getLayoutResId())
        initViewModel()
        initObser()
        initDataBeforInitView()
        initVie()
        initDataAfterInitView()

    }


    //初始化viewmodel
    open protected fun initViewModel() {

    }

    //初始化页面
    abstract fun initVie()


    //初始化livedata的监听,
    abstract fun initObser()

    //获取数据在initview之前
    abstract fun initDataBeforInitView()

    //获取数据在initview之后
    abstract fun initDataAfterInitView()


    //页面消费之前,解绑
    override fun onDestroy() {
        if (binding != null) {
            binding.unbind()
        }
        super.onDestroy()
    }


}

ViewModelDataBinding基础类:

abstract class BaseViewModelBindActivity<T : ViewDataBinding, V : BaseViewModel>() :
    BaseDataBindModelActivity<T>() {

    lateinit var viewModel: V

    override fun initViewModel() {
        super.initViewModel()
        val type = javaClass.genericSuperclass
        if (type != null && type is ParameterizedType) {
            val actualTypeArguments = type.actualTypeArguments
            val tClass = actualTypeArguments[1]

            viewModel= AndroidViewModelFactory.getInstance(application).create(tClass as Class<V>)
        }


        lifecycle.addObserver(viewModel)
    }


    override fun onDestroy() {
        super.onDestroy()
        lifecycle.removeObserver(viewModel)
    }




}

通过以上的配置,基本已完成了MVVM的搭建。

小时牛刀:

class MyTestViewBindActivity : BaseViewModelBindActivity<TestViewBind, MyViewModel>() {

    override fun getLayoutResId(): Int {
        return R.layout.layout_test_view_bind
    }

    override fun initVie() {
        binding.btnTest.setOnClickListener {
            viewModel.showToast("你好")
        }

        binding.btnInit.setOnClickListener {

            //调用了初始化事件
            viewModel.initData()
        }
    }

    override fun initObser() {

        //数据订阅事件
        viewModel.initLiveData.observe(this) {
            binding.textInfo.text = it
        }


    }

    override fun initDataBeforInitView() {

    }

    override fun initDataAfterInitView() {

    }
}

绑定的页面生命周期回调:

运行效果

五、总结

1.通过以上学习,完成了MVVM的基础结构与如何架构一个MVVM页面出来。Demo中也基本完成了大家的难点问题。

2.如果不了解生命周期的可以参考Demo中直接拿去用,避免处理不好导致内存泄露

3.MVVM需要databinding的参与,如果不了解的小伙伴直接看我的DataBinding文章,看完直接上项目使用是没任何问题,有问题我得文章中也会提出,这边都是干货,都是博主自己总结与写出来的。希望大家能够受益。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/931397.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PyCharm软件安装包分享

目录 一、软件简介 二、软件下载 一、软件简介 PyCharm是一种集成开发环境&#xff08;IDE&#xff09;&#xff0c;专门为Python开发者设计。它是由捷克软件公司JetBrains开发的&#xff0c;为Python开发人员提供了高效、易用和功能丰富的工具集。 以下是PyCharm软件的主要…

强化学习在游戏AI中的应用与挑战

文章目录 1. 强化学习简介2. 强化学习在游戏AI中的应用2.1 游戏智能体训练2.2 游戏AI决策2.3 游戏测试和优化 3. 强化学习在游戏AI中的挑战3.1 探索与利用的平衡3.2 多样性的应对 4. 解决方法与展望4.1 深度强化学习4.2 奖励设计和函数逼近 5. 总结 &#x1f389;欢迎来到AIGC人…

常用的Selenium基础使用模板和简单封装

前言 近来又用上了 Selneium &#xff0c;因为反复用到&#xff0c;所以在这里将一些常用的方法封装起来&#xff0c;方便后续的使用。 在这篇文章中&#xff0c;我们将探讨 Selenium 的基础模板和基础封装&#xff0c;以便更好地理解 Selenium 的使用方法。 在Selenium的使…

【杂谈分享】关于我去HVV当猴子这件事——HVV日记

目录 前言 序幕 开局 入世 破妄 终章 前言 今年第一次参加HVV行动。去当蓝队专家&#xff08;cai niao&#xff09;。大概是六月末&#xff0c;领导说今年的HVV派我去参加。毕竟是第一次参加&#xff0c;因此虽然可能就没办法放假了&#xff0c;而且也没有额外工资&…

python基础教程:re模块用法详解

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 一、正则表达式的特殊字符介绍 正则表达式 &#x1f447; &#x1f447; &#x1f447; 更多精彩机密、教程&#xff0c;尽在下方&#xff0c;赶紧点击了解吧~ 素材、视频教程、完整代码、插件安装教程我都准备好了&a…

【Linux】进程状态|僵尸进程|孤儿进程

前言 本文继续深入讲解进程内容——进程状态。 一个进程包含有多种状态&#xff0c;有运行状态&#xff0c;阻塞状态&#xff0c;挂起状态&#xff0c;僵尸状态&#xff0c;死亡状态等等&#xff0c;其中&#xff0c;阻塞状态还包含深度睡眠和浅度睡眠状态。 个人主页&#xff…

SQL Server软件安装包分享

目录 一、软件简介 二、软件下载 一、软件简介 SQL Server是一种关系型数据库管理系统&#xff0c;由美国微软公司开发。它被设计用于存储、管理和查询数据&#xff0c;被广泛应用于企业级应用、数据仓库和电子商务等场景。 以下是SQL Server软件的主要特点和功能&#xff1…

STM32 BOOT 启动配置 ISP升级 介绍

启动配置 在STM32F10xxx里&#xff0c;可以通过BOOT[1:0]引脚选择三种不同启动模式。 启动模式选择引脚启动模式说明BOOT1BOOT0X0主闪存存储器主闪存存储器被选为启动区域01系统存储器系统存储器被选为启动区域11内置SRAM内置SRAM被选为启动区域 在系统复位后&#xff0c; S…

java八股文面试[多线程]——有几种创建线程的方式

this逃逸问题&#xff1a;构造器中启动线程。 面试题&#xff1a; 用Thread和Runable创建线程的差别 一、Runnable和Thread的区别 继承性&#xff1a;Thread是一个类&#xff0c;因此如果继承Thread类&#xff0c;子类就不能再继承其他的类了&#xff0c;而实现Runnable接口…

JavaFX 加载 fxml 文件

JavaFX 加载 fxml 文件主要有两种方式&#xff0c;第一种方式通过 FXMLLoader 类直接加载 fxml 文件&#xff0c;简单直接&#xff0c;但是有些控件目前还不知道该如何获取&#xff0c;所以只能显示&#xff0c;目前无法处理。第二种方式较为复杂&#xff0c;但是可以使用与 fx…

mysql 逻辑架构

连接层 客户端和服务器建立连接&#xff0c;客户端发送sql 到 服务器端 服务层 引擎层 查看现有的 存储引擎 show engines&#xff1b; 存储层

电子器件系列56:ltc1799(定时器)

定时IC芯片是一种具有定时功能的集成电路&#xff0c;常用于计时、时钟、频率合成等应用。以下是一些常见的定时IC芯片&#xff1a; 1. 555定时器芯片&#xff1a;最常见的定时IC芯片之一&#xff0c;可用于产生各种定时信号和脉冲。 2. 556双555定时器芯片&#xff1a;由两个5…

OLED透明屏曲面技术:创新突破引领显示行业未来

OLED透明屏曲面技术作为一项重要的显示技术创新&#xff0c;正在成为显示行业的焦点&#xff0c;其引人注目的优势和广泛应用领域使其备受关注。 本文将详细介绍OLED透明屏曲面技术的优势、应用领域以及市场前景&#xff0c;同时展望其未来的发展趋势&#xff0c;以期带给读者…

数据工厂调研及结果展示

数据工厂 一、背景 在开发自测、测试迭代测试、产品验收的过程中&#xff0c;都需要各种各样的前置数据&#xff0c;大致分为如下几类&#xff1a; 账号&#xff08;实名、权益等级、注册等&#xff09; 货源&#xff08;优货、急走、相似、一手、普通货源等&#xff09; …

Linux下Qt配置opencv环境(ippicv,ffmpeg手动配置)

1.opencv配置使用问题 opencv在cmake的时候有两个问题&#xff0c;ippicv长时间卡住下载失败&#xff0c;ffmpeg不会卡住但是也不会配置成功。所以这两个包只能手动下载安装。 ippicv是什么 OpenCV设计用于高效的计算&#xff0c;十分强调实时应用的开发。它由C语言编写并进行了…

腾讯云服务器地域有什么区别?怎么选择合适?

腾讯云服务器地域有什么区别&#xff1f;怎么选择比较好&#xff1f;地域选择就近原则&#xff0c;距离地域越近网络延迟越低&#xff0c;速度越快。关于地域的选择还有很多因素&#xff0c;地域节点选择还要考虑到网络延迟速度方面、内网连接、是否需要备案、不同地域价格因素…

聚观早报 | 青瓷游戏上半年营收3.34亿元;如祺出行冲击IPO

【聚观365】8月26日消息 青瓷游戏上半年营收3.34亿元 如祺出行冲击IPO 索尼互动娱乐将收购Audeze 昆仑万维上半年净利润3.6亿元 T-Mobile计划在未来五周内裁员5000人 青瓷游戏上半年营收3.34亿元 青瓷游戏发布截至2023年6月30日止的中期业绩&#xff0c;财报显示&#xf…

聚类分析 | MATLAB实现基于DBSCAD密度聚类算法可视化

聚类分析 | MATLAB实现基于LP拉普拉斯映射的聚类可视化 目录 聚类分析 | MATLAB实现基于LP拉普拉斯映射的聚类可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 基于DBSCAD密度聚类算法可视化&#xff0c;MATLAB程序。 使用带有KD树加速的dbscan_with_kdtree函数进行…

AI绘画 | Discord的最强7款AI插件整理汇总

hi&#xff0c;同学们&#xff0c;我是赤辰&#xff0c;本周起&#xff0c;我们将开启AI工具教程篇的栏目&#xff0c;每天会更新1篇AI教程或推荐实用AI工具&#xff0c;文章底部准备了粉丝福利&#xff0c;看完可以领取&#xff01; 今天给大家整理了Discord的最强7款AI插件汇…