Android开发框架MVC-MVP-MVVM-MVI的演变Demo

目录
  • Android框架的历史演变
  • 一. MVC框架
  • 二. MVP框架
  • 三. MVVM框架
    • 3.1 半MVVM框架
    • 3.2 带DataBinding的MVVM框架
  • 四. MVI框架

Android框架的历史演变

记得最开始入门Android的时候,还未流行MVP,都是MVC一把梭,后面工作了就是使用了MVP,当时学习的时候好难理解它的回调。

到目前主流的MVVM,其实就是MVP的升级版,再到最新的MVI使用意图传输,隔离各层级的直接调用。我算是经历了Android框架变迁的全过程。

这里记录一下各框架的简单Demo用例。

一. MVC框架

经典MVC分为:

Model 模型层 : 数据和网络

View 视图层 : 视图的展示

Controller 控制层 : 逻辑控制,调用模型驱动视图

一般我们是把一个xml看作一个View层, Activity看作一个Control层 , Model层则是由相关的数据操作类。

Model层:

class OtherModel : BaseRepository() {
    /**
     * 使用扩展方法,请求网络
     */
    suspend inline fun getIndustry(): OkResult<List<Industry>> {
        return extRequestHttp {
            DemoRetrofit.apiService.getIndustry(
                Constants.NETWORK_CONTENT_TYPE,
                Constants.NETWORK_ACCEPT_V1
            )
        }
    }
}

Controller层:

class MVCActivity : AbsActivity() {
    private val mOtherModel: OtherModel by lazy { OtherModel() }
    override fun setContentView() {
        setContentView(R.layout.activity_demo14_1)
    }
    override fun init() {
        val btnGetData = findViewById<Button>(R.id.btn_get_data)
        btnGetData.click {
            requestIndustry()
        }
    }
    private fun requestIndustry() {
        //MVC中Activity就是Controller,直接调用接口,获取数据之后直接操作xml控件刷新
        lifecycleScope.launch {
            //开始Loading
            LoadingDialogManager.get().showLoading(this@MVCActivity)
            val result = mOtherModel.getIndustry()
            result.checkSuccess {
                //处理成功的信息
                toast("list:$it")
                //doSth...
            }
            LoadingDialogManager.get().dismissLoading()
        }
    }
}

XML就是View层,获取到信息展示到XML中。

这样分工其实也是很明确的,但是一旦逻辑过多,会导致Activity太臃肿。Activcity中又是Model又是View,耦合性太强,记得那时候一个Activity中上千行代码都是平平常常。

为了解决这个问题,大家开始使用MVP架构。

二. MVP框架

MVP框架的出现,各个模块权责分明,各干各的活,降低了耦合,减少Activity的臃肿。

Model层:还是MVC那个Model。
View层:接口定义由Activity实,用于操作相应的UI。
Presenter层:用于Model和View的桥梁,负责Model与View的交互

那更复杂的一点的,就是其中加入Contract契约类,把指定页面的Presenter和View等关联起来,方便维护。

View接口定义

interface IDemoView {
    fun showLoading()
    fun hideLoading()
    fun getIndustrySuccess(list: List<Industry>?)
    fun getIndustryFailed(msg: String?)
}

Presenter的实现:

class DemoPresenter(private val view: IDemoView) {
    private val mOtherModel: OtherModel by lazy { OtherModel() }
    //获取行业数据
    fun requestIndustry(lifecycleScope: LifecycleCoroutineScope) {
        lifecycleScope.launch {
            //开始Loading
            view.showLoading()
            val result = mOtherModel.getIndustry()
            result.checkResult({
                //处理成功的信息
                toast("list:$it")
                view.getIndustrySuccess(it)
            }, {
                //失败
                view.getIndustryFailed(it)
            })
            view.hideLoading()
        }
    }
}

Activity的实现:

class MVPActivity : AbsActivity(), IDemoView {
    private lateinit var mPresenter: DemoPresenter
    override fun setContentView() {
        setContentView(R.layout.activity_demo14_1)
    }
    override fun init() {
        //创建Presenter
        mPresenter = DemoPresenter(this)
        val btnGetData = findViewById<Button>(R.id.btn_get_data)
        btnGetData.click {
            //通过Presenter调用接口
            mPresenter.requestIndustry(lifecycleScope)
        }
    }
    //回调再次触发
    override fun showLoading() {
        LoadingDialogManager.get().showLoading(this)
    }
    override fun hideLoading() {
        LoadingDialogManager.get().dismissLoading()
    }
    override fun getIndustrySuccess(list: List<Industry>?) {
        //popupIndustryData
    }
    override fun getIndustryFailed(msg: String?) {
        //showErrorMessage
    }
}

当时MVP框架是火遍一时,当时面试要不会这个,那都不好意思说是做安卓的。

虽然它有一些缺点,比如太复杂,每次都要写重复的View,修改麻烦,回调地狱,数据交互体验不佳,无法感知生命周期,重建页面无法自动恢复数据,耦合还是有很多,等等。但是在当时没有替代品的选择下,它是当之无愧的王。

但是当谷歌出了Jetpack,当ViewModel+LiveData+Lifecycles的出现给了我们新的选择 MVVM框架开始出现并迅猛发展。

三. MVVM框架

这里先说一点有争议的点。 有些人认为,只要用上ViewModel+LiveData这些就算MVVM框架 Model+View+ViewModel嘛。 有些人认为,MVVM的意思是数据驱动,最大的亮点是数据绑定,使用DataBinding的才算MVVM。 其实这个也没有官方的定义,世上本无框架,用的人多了才出现框架名字,约定俗成的东西,你想怎么定义就怎么定义,那我姑且称为前者为半MVVM后者为MVVM吧

3.1 半MVVM框架

其实可以理解为MVP的升级版,去掉了View的接口回调,保存了ViewModel的特性

Model层:还是MVC那个Model。
View层:Activity,用于操作相应的UI。
ViewModel:还是MVP那个Presenter,只是用ViewModel实现。

ViewModel实现: 可以看到代码确实相比MVP少了很多

class DemoViewModel @ViewModelInject constructor(
    private val mRepository: Demo5Repository,
    @Assisted val savedState: SavedStateHandle
) : BaseViewModel() {
    val liveData = MutableLiveData<List<Industry>?>()
    //获取行业数据
    fun requestIndustry() {
        viewModelScope.launch {
            //开始Loading
            loadStartLoading()
            val result = mRepository.getIndustry()
            result.checkResult({
                //处理成功的信息
                toast("list:$it")
                liveData.value = it
            }, {
                //失败
                liveData.value = null
            })
            loadHideProgress()
        }
    }
}

Activity的实现:

@AndroidEntryPoint
class MVVMActivity : BaseVMActivity<DemoViewModel>() {
    override fun getLayoutIdRes(): Int = R.layout.activity_demo14_1
    override fun init() {
        //自动注入ViewModel,调用接口通过LiveData回调
        mViewModel.requestIndustry()
    }
    override fun startObserve() {
        //获取到网络数据之后改变xml对应的值
        mViewModel.liveData.observe(this) {
            it?.let {
                // popopIndustryData
            }
        }
    }
}

3.2 带DataBinding的MVVM框架

特别是现在kotlin那种直接拿id使用的插件已经被官方标记为过时,还不赶紧用DataBinding或ViewBinding?

ViewModel实现:

class DemoViewModel @ViewModelInject constructor(
    private val mRepository: Demo5Repository,
    @Assisted val savedState: SavedStateHandle
) : BaseViewModel() {
    val liveData = MutableLiveData<List<Industry>?>()
    //获取行业数据
    fun requestIndustry() {
        viewModelScope.launch {
            //开始Loading
            loadStartLoading()
            val result = mRepository.getIndustry()
            result.checkResult({
                //处理成功的信息
                toast("list:$it")
                liveData.value = it
            }, {
                //失败
                liveData.value = null
            })
            loadHideProgress()
        }
    }
}

Repository的实现:其实和Model差不多的意思,数据仓库而已,下面的一些注解是用到了Hilt依赖注入,不用直接new对象也是可以的,不要在意一些细节。

@Singleton
class Demo5Repository @Inject constructor() : BaseRepository() {
    suspend inline fun getIndustry(): OkResult<List<Industry>> {
        return extRequestHttp {
            DemoRetrofit.apiService.getIndustry(
                Constants.NETWORK_CONTENT_TYPE,
                Constants.NETWORK_ACCEPT_V1
            )
        }
    }
}

Activity的实现: 内部做了一些基类的封装,事件处理封装为对象,viewmodel和事件对象在xml中做了引用

@AndroidEntryPoint
class MVVM2Activity : BaseVDBActivity<DemoViewModel, ActivityDemo142Binding>() {
    private val clickProxy: ClickProxy by lazy { ClickProxy() }
    override fun getDataBindingConfig(): DataBindingConfig {
        return DataBindingConfig(R.layout.activity_demo14_2, BR.viewModel, mViewModel)
            .addBindingParams(BR.click, clickProxy)
    }
    override fun init() {
    }
    override fun startObserve() {
    }
    /**
     * DataBinding事件处理
     */
    inner class ClickProxy {
        fun getData() {
            //MVVM直接调用网络请求,结果在xml中自动显示
            mViewModel.requestIndustry()
        }
    }
}

Xml的实现: 注意引用指向的包名要写对,写对了可以直接跳转过去的。

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:binding="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">
    <data>
        <variable
            name="viewModel"
            type="com.guadou.kt_demo.demo.demo14_mvi.mvvm1.DemoViewModel" />
        <variable
            name="click"
            type="com.guadou.kt_demo.demo.demo14_mvi.mvvm2.MVVM2Activity.ClickProxy" />
    </data>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/picture_color_blue"
        android:orientation="vertical">
        <com.guadou.lib_baselib.view.titlebar.StatusbarGrayView
            android:id="@+id/status_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="获取数据"
            binding:clicks="@{click.getData}" />
        <TextView
            android:id="@+id/tv_message"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@{viewModel.liveData.toString()}" />
    </LinearLayout>
</layout>

这样就完成了一个基于数据驱动的DataBinding的MVVM。 如果上面一些代码如果看不太明白,后面我可能会出DataBinding的封装并开源。

截止到发稿日期为止,目前市面上最流行的还是MVVM框架,此框架唯一的槽点可能就是Databinding的不好调试吧,一旦出问题,有时候报错信息莫名其妙的,没有指向XML中某个数据或语法的错误,需要对DataBinding有一定的了解。 不过AS现在貌似越来越智能了,报错信息都还指向蛮清晰的。MVVM完全可用的。

四. MVI框架

由于是出来没多久,具体是不是叫MVI框架这个名字还不确定,大家都这么叫,姑且就叫MVI吧。伴随Compose出现的框架,主流用于Compose应用。

MVI框架是由Model View Intent组成的。可以算上MVVM的升级版,在之前我们都是通过在Activity中直接调用ViewModel的方法,现在改为发出操作指令,由ViewModel解析指令,调用对应的方法,回调给Activity。

比如一个DemoActivity需要获取行业数据,学校数据,等。那么就可以把数据和操作都封装成指定的对象。

    //当前页面所需的数据与状态
    data class Demo14ViewState(
        val industrys: List<Industry> = emptyList(),
        val schools: List<SchoolBean> = emptyList(),
        var isChanged: Boolean = false
    ) : BaseViewState()
    //当前页面需要的事件定义
    sealed class DemoAction {
        object RequestIndustry : DemoAction()
        object RequestSchool : DemoAction()
        object RequestAllData : DemoAction()
        data class UpdateChanged(val isChange: Boolean) : DemoAction()
    }

Activity调用相关的接口就不是直接调用ViewModel的方法,而是:

   override fun init() {
        //发送Intent指令,具体的实现由ViewModel实现
        mViewModel.dispatch(Damo14ViewModel.DemoAction.RequestAllData)
    }

那么ViewModel就需要解析指令:

    //Action分发入口
    fun dispatch(action: DemoAction) {
        when (action) {
            is DemoAction.RequestIndustry -> requestIndustry()
            is DemoAction.RequestSchool -> requestSchool()
            is DemoAction.RequestAllData -> getTotalData()
            is DemoAction.UpdateChanged -> changeData(action.isChange)
        }
    }
    //获取行业数据
    private fun requestIndustry() {
      //xxx
    }

完整的代码如下:

ViewModel的实现:

class Damo14ViewModel @ViewModelInject constructor(
    private val mRepository: Demo5Repository,
    @Assisted val savedState: SavedStateHandle
) : BaseViewModel() {
    private val _viewStates: MutableLiveData<Demo14ViewState> = MutableLiveData(Demo14ViewState())
    //只需要暴露一个LiveData,包括页面所有状态
    val viewStates: LiveData<Demo14ViewState> = _viewStates
    //Action分发入口
    fun dispatch(action: DemoAction) {
        when (action) {
            is DemoAction.RequestIndustry -> requestIndustry()
            is DemoAction.RequestSchool -> requestSchool()
            is DemoAction.RequestAllData -> getTotalData()
            is DemoAction.UpdateChanged -> changeData(action.isChange)
        }
    }
    //获取行业数据
    private fun requestIndustry() {
        viewModelScope.launch {
            //开始Loading
            loadStartLoading()
            val result = mRepository.getIndustry()
            result.checkSuccess {
                _viewStates.setState {
                    copy(industrys = it ?: emptyList())
                }
            }
            loadHideProgress()
        }
    }
    //获取学校数据
    private fun requestSchool() {
        viewModelScope.launch {
            //开始Loading
            loadStartLoading()
            val result = mRepository.getSchool()
            result.checkSuccess {
                _viewStates.setState {
                    copy(schools = it ?: emptyList())
                }
            }
            loadHideProgress()
        }
    }
    //获取全部数据
    private fun getTotalData() {
        //默认执行在主线程的协程-必须用(可选择默认执行在IO线程的协程)
        launchOnUI {
            //开始Loading
            loadStartProgress()
            val industryResult = async {
                mRepository.getIndustry()
            }
            val schoolResult = async {
                mRepository.getSchool()
            }
            //一起处理数据
            val industry = industryResult.await()
            val school = schoolResult.await()
            //如果都成功了才一起返回
            if (industry is OkResult.Success && school is OkResult.Success) {
                loadHideProgress()
                //设置多种LiveData
                _viewStates.setState {
                    copy(industrys = industry.data ?: emptyList(), schools = school.data ?: emptyList())
                }
            }
        }
    }
    //改变状态
    private fun changeData(isChanged: Boolean) {
        _viewStates.setState {
            copy(isChanged = isChanged)
        }
    }
    //当前页面所需的数据与状态
    data class Demo14ViewState(
        val industrys: List<Industry> = emptyList(),
        val schools: List<SchoolBean> = emptyList(),
        var isChanged: Boolean = false
    ) : BaseViewState()
    //如果想再度封装,也可以把回调的结果封装成类似Action的对象,由页面判断回调的是哪一种类型,进行相关的操作
    //这样就不需要使用LiveData回调了,LiveData就只是作为保存数据的功能,由DemoEvent回调
//    sealed class DemoEvent {
//        object PopBack : DemoEvent()
//        data class ErrorMessage(val message: String) : DemoEvent()
//    }
    //当前页面需要的事件定义
    sealed class DemoAction {
        object RequestIndustry : DemoAction()
        object RequestSchool : DemoAction()
        object RequestAllData : DemoAction()
        data class UpdateChanged(val isChange: Boolean) : DemoAction()
    }
}

Activity的实现:

@AndroidEntryPoint
class Demo14Activity : BaseVDBActivity<Damo14ViewModel, ActivityDemo14Binding>() {
    private val clickProxy: ClickProxy by lazy { ClickProxy() }
    companion object {
        fun startInstance() {
            commContext().let {
                it.startActivity(Intent(it, Demo14Activity::class.java).apply {
                    addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                })
            }
        }
    }
    override fun getDataBindingConfig(): DataBindingConfig {
        return DataBindingConfig(R.layout.activity_demo14)
            .addBindingParams(BR.click, clickProxy)
    }
    @SuppressLint("SetTextI18n")
    override fun startObserve() {
        //监听两者数据变化
        mViewModel.viewStates.observeState(
            this,
            Damo14ViewModel.Demo14ViewState::industrys,
            Damo14ViewModel.Demo14ViewState::schools
        ) { industry, school ->
            YYLogUtils.w("industry: $industry ; school: $school")
        }
        //只监听changed的变换
        mViewModel.viewStates.observeState(this, Damo14ViewModel.Demo14ViewState::isChanged) {
            if (it) {
                val industry = mViewModel.viewStates.value?.industrys
                val school = mViewModel.viewStates.value?.schools
                mBinding.tvMessage.text = "industry: $industry ; school: $school"
            }
        }
    }
    override fun init() {
        //发送Intent指令,具体的实现由ViewModel实现
        mViewModel.dispatch(Damo14ViewModel.DemoAction.RequestAllData)
    }
    /**
     * DataBinding事件处理
     */
    inner class ClickProxy {
        fun getData() {
            //发送Intent指令,具体的实现由ViewModel实现
//            mViewModel.dispatch(Damo14ViewModel.DemoAction.RequestIndustry)
//            mViewModel.dispatch(Damo14ViewModel.DemoAction.RequestSchool)
            mViewModel.dispatch(Damo14ViewModel.DemoAction.UpdateChanged(true))
        }
    }
}

注意,有些MVI的写法是回调给Activity的方式也是用对象封装如我注释的代码:

    //如果想再度封装,也可以把回调的结果封装成类似Action的对象,由页面判断回调的是哪一种类型,进行相关的操作
    //这样就不需要使用LiveData回调了,LiveData就只是作为保存数据的功能,由DemoEvent回调
//    sealed class DemoEvent {
//        object PopBack : DemoEvent()
//        data class ErrorMessage(val message: String) : DemoEvent()
//    }

也可以使用LiveData返回,我这里使用扩展方法observeState方法来监听,这样可以保证只有你监听的对象发生了变化才会收到回调。这个扩展方法在MVVM框架也能使用。

扩展方法如下:

import androidx.lifecycle.*
import kotlin.reflect.KProperty1
/**
 * @auther Newki
 * @date 2022/2/10
 * @description LiveData的扩展 支持MVI模式 订阅单个LiveData实现监听不同的操作与数据
 */
//监听一个属性
fun <T, A> LiveData<T>.observeState(
    lifecycleOwner: LifecycleOwner,
    prop1: KProperty1<T, A>,
    action: (A) -> Unit
) {
    this.map {
        StateTuple1(prop1.get(it))
    }.distinctUntilChanged().observe(lifecycleOwner) { (a) ->
        action.invoke(a)
    }
}
//监听两个属性
fun <T, A, B> LiveData<T>.observeState(
    lifecycleOwner: LifecycleOwner,
    prop1: KProperty1<T, A>,
    prop2: KProperty1<T, B>,
    action: (A, B) -> Unit
) {
    this.map {
        StateTuple2(prop1.get(it), prop2.get(it))
    }.distinctUntilChanged().observe(lifecycleOwner) { (a, b) ->
        action.invoke(a, b)
    }
}
//监听三个属性
fun <T, A, B, C> LiveData<T>.observeState(
    lifecycleOwner: LifecycleOwner,
    prop1: KProperty1<T, A>,
    prop2: KProperty1<T, B>,
    prop3: KProperty1<T, C>,
    action: (A, B, C) -> Unit
) {
    this.map {
        StateTuple3(prop1.get(it), prop2.get(it), prop3.get(it))
    }.distinctUntilChanged().observe(lifecycleOwner) { (a, b, c) ->
        action.invoke(a, b, c)
    }
}
internal data class StateTuple1<A>(val a: A)
internal data class StateTuple2<A, B>(val a: A, val b: B)
internal data class StateTuple3<A, B, C>(val a: A, val b: B, val c: C)
//更新State
fun <T> MutableLiveData<T>.setState(reducer: T.() -> T) {
    this.value = this.value?.reducer()
}

太干了,一张图都没上,最后总结一下:

世界上本无框架,用的人多了就成了框架,适合自己的才是好的。不是一定说出了最新框架我就要用最新的框架,理解之后再使用才能得心应手。

个人目前平时开发中用的也是MVVM框架。后期会出一些MVVM的封装和用法开源

以上就是Android开发框架MVC-MVP-MVVM-MVI的演变Demo的详细内容,更多关于Android框架MVC MVP MVVM MVI的资料请关注我们其它相关文章!

(0)

相关推荐

  • Pytorch 使用Google Colab训练神经网络深度学习

    目录 学习前言 什么是Google Colab 相关链接 利用Colab进行训练 一.数据集与预训练权重的上传 1.数据集的上传 2.预训练权重的上传 二.打开Colab并配置环境 1.笔记本的创建 2.环境的简单配置 3.深度学习库的下载 4.数据集的复制与解压 5.保存路径设置 三.开始训练 1.标注文件的处理 2.训练文件的处理 3.开始训练 断线怎么办? 1.防掉线措施 2.完了还是掉线呀? 总结 学习前言 Colab是谷歌提供的一个云学习平台,Very Nice,最近卡不够用了决定去白

  • Google Kubernetes Engine 集群实战详解

    目录 GKE 集群介绍 K8s 带来的好处 使用 GKE 编排集群 GKE 集群介绍 Google Kubernetes Engine (GKE) 集群由 Kubernetes 开源集群管理系统提供支持.Kubernetes 为用户提供了与容器集群进行交互的机制.您可以使用 Kubernetes 命令和资源来部署和管理应用.执行管理任务.设置政策,以及监控您部署的工作负载的运行状况. K8s 带来的好处 自动管理 对应用容器进行监控和活跃性探测 自动扩缩 滚动更新 Google Cloud 上的

  • Google Kaptcha验证码生成的使用实例说明

    目录 Kaptcha是什么? 怎么使用Kaptcha? 1.首先下载jar包 2.配置kaptcha 3.将验证码保存进session中 4.验证码校验 Kaptcha验证码配置 效果图如下 Kaptcha是什么? kaptcha 是谷歌开源的非常实用的验证码生成工具,基于SimpleCaptcha的开源项目.使用Kaptcha 生成验证码十分简单并且参数可以进行自定义.只需添加jar包配置下就可以使用,通过配置,可以自己定义验证码大小.颜色.显示的字符等等.下面就来讲一下如何使用kaptcha

  • 开箱即用的Google与百度定位坐标系转换实例

    目录 集成谷歌定位与百度定位并在地图上显示 项目背景 一. 集成谷歌定位 定位Api使用流程: 二. 集成百度定位 Application中初始化SDK 三. 坐标系转换与地图上的显示 集成谷歌定位与百度定位并在地图上显示 项目背景 东南亚某小国的App,需要用到定位与地图显示,我们都知道海外人士都是喜欢谷歌地图与谷歌定位的,那么必然是要优先使用谷歌定位的,但是中国手机卖的很好,部分中国手机的海外版是没有谷歌服务的,那么我使用百度地图进行降级处理. 两者使用的定位坐标系不同,如果需要在谷歌地图上

  • 使用GoogleContainerTools容器化jib构建docker镜像

    目录 前言碎语 插件配置 配置详解 插件命令使用 集成插件生命周期 文末结语 前言碎语 今天分享一个在容器化过程中非常重要的一个工具,java应用docker镜像build工具jib,这个工具是谷歌团队研发开源的,特点是不依赖docker守护进程,直白点说就是本地环境不安装docker环境也可以打包docker镜像.不用依赖维护Dockerfile,而且基于java打包插件可以轻松嵌入到java本身的构建生命周期中(本文使用maven).可以说是java容器化构建利器. 插件配置 <plugin

  • Google 开发Android MVP架构Demo深入解析

    目录 1.什么是MVP? 2.Google官方的MVP 3.V1.1 My MVP V1 4.V1.2 My MVP V2 1.什么是MVP? Google在2016年推出了官方的Android MVP架构Demo,本文主要分析一下官方的MVP Demo,并且借由自己的一些经验,提出一些学习过程中,遇到的问题和自己的改进.封装措施. MVP架构已经推出很多年了,现在已经非常普及了,我在这里就不过多介绍,简单的说,它分为以下三个层次: Model:数据模型层,主要用来数据处理,获取数据: View

  • ASP.NET小结之MVC, MVP, MVVM比较以及区别(一)

    MVC, MVP和MVVM都是用来解决界面呈现和逻辑代码分离而出现的模式.以前只是对它们有部分的了解,没有深入的研究过,对于一些里面的概念和区别也是一知半解.现在一边查资料,并结合自己的理解,来谈一下对于这三种模式思想的理解,以及它们的区别.欢迎各位高手拍砖. 阅读目录: 复制代码 代码如下: 一. MVC, MVP, MVVM诞生的需求? 二. 一段典型的耦合代码 三. MVC模式 3.1 主动MVC 3.2 被动MVC 3.3 Web应用中的MVC框架 3.4 MVC总结 一,MVC, MV

  • ASP.NET小结之MVC, MVP, MVVM比较以及区别(二)

    上一篇得到大家的关注,非常感谢.由于自己对于这些模式的理解也是有限,对于这些模式的比较,是结合自己的理解,一些地方不一定准确,但是只有亮出自己的观点,才能抛砖引玉不是? 欢迎各位拍砖.:) 复制代码 代码如下: 阅读目录: 四. MVP模式 4.1 MVP的思想 4.2 UI界面接口化 4.3 Presenter -- Model和View之间的桥梁 4.4 MVP的代码结构和时序图 4.5 MVP模式总结 五. MVVM模式 5.1 MVVM模式的设计思想 5.2 MVVM模式结构图 六. M

  • Android开发框架MVC-MVP-MVVM-MVI的演变Demo

    目录 Android框架的历史演变 一. MVC框架 二. MVP框架 三. MVVM框架 3.1 半MVVM框架 3.2 带DataBinding的MVVM框架 四. MVI框架 Android框架的历史演变 记得最开始入门Android的时候,还未流行MVP,都是MVC一把梭,后面工作了就是使用了MVP,当时学习的时候好难理解它的回调. 到目前主流的MVVM,其实就是MVP的升级版,再到最新的MVI使用意图传输,隔离各层级的直接调用.我算是经历了Android框架变迁的全过程. 这里记录一下

  • Android开发框架之自定义ZXing二维码扫描界面并解决取景框拉伸问题

    先给大家展示下效果图: 扫描内容是下面这张,二维码是用zxing库生成的 由于改了好几个类,还是去年的事都忘得差不多了,所以只能上这个类的代码了,主要就是改了这个CaptureActivity.java package com.zxing.activity; import java.io.IOException; import java.util.Vector; import android.app.Activity; import android.content.Intent; import

  • web面试MVC与MVVM区别及Vue为什么不完全遵守MVVM解答

    目录 MVC和MVVM区别 前述 MVC 概述 优缺点 MVVM 概述 MVVM实现者 - Vue Vue为什么没有完全遵守MVVM? MVC和MVVM区别 前述 首先, 这两种都只是一种思想, 一种设计模式 很多编程语言根据这种思想设计出了很多框架, 例如Java中的SpringMVC, PHP中的ThinkPHP , JavaScript中的Vue.React.Angular等 MVC 概述 1.数据要渲染到视图上   定义一个模板引擎   得到数据   再将数据渲染到模板引擎中 2.视图操

  • Vue组件大全包括(UI组件,开发框架,服务端,辅助工具,应用实例,Demo示例)

    Vue是一款比较流行的JS库,本文为大家介绍一些Vue组件,包括UI组件,开发框架,服务端,辅助工具,应用实例,Demo示例等开源项目 一.Vue常用UI组件 element ★11612 - 饿了么出品的Vue2的web UI工具套件 Vux ★7503 - 基于Vue和WeUI的组件库 iview ★5801 - 基于 Vuejs 的开源 UI 组件库 mint-ui ★5517 - Vue 2的移动UI元素 vue-material ★2790 - 通过Vue Material和Vue 2

  • Android屏幕锁屏弹窗的正确姿势DEMO详解

    在上篇文章给大家介绍了Android程序开发仿新版QQ锁屏下弹窗功能.今天通过本文给大家分享android锁屏弹窗的正确姿势. 最近在做一个关于屏幕锁屏悬浮窗的功能,于是在网上搜索了很多安卓屏幕锁屏的相关资料,鉴于网上的资料比较零碎,所以我在这里进行整理总结.本文将从以下两点对屏幕锁屏进行解析: 1. 如何监听系统屏幕锁屏 2. 如何在锁屏界面弹出悬浮窗 如何监听系统屏幕锁屏 经过总结,监听系统的锁屏可以通过以下两种方式: 1) 代码直接判定 2) 接收广播 1) 代码直接判定 代码判断方式,也

  • Android实现调用系统相册和拍照的Demo示例

    本文讲述了Android实现调用系统相册和拍照的Demo示例.分享给大家供大家参考,具体如下: 最近我在群里看到有好几个人在交流说现在网上的一些Android调用系统相册和拍照的demo都有bug,有问题,没有一个完整的.确实是,我记得一个月前,我一同学也遇到了这样的问题,在低版本的系统中没问题,用高于4.4版本的系统就崩溃.所以,我还是想提取出来,给大家整理一下,一个比较完整无bug的demo,让大家收藏,留着以后用. 其实对于调用手机图库,高版本的系统会崩溃,是因为获取方法变了,所以我们应该

  • 关于Android高德地图的简单开发实例代码(DEMO)

    废话不多说了,直接给大家上干货了. 以下为初次接触时 ,练手的DEMO import android.app.Activity; import android.app.ProgressDialog; import android.content.ContentValues; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatab

  • 详解Android中的MVP架构分解和实现

    1.概述 传统的Android开发架构一般是MVC模式, Model:业务逻辑和实体模型 View:对应于布局文件 Controllor:对应于Activity 单独从逻辑看起来非常好,与我们做Web开发时,开发模式类似,但在实际开发中,View对应于布局文件,实际上关于该布局文件中的数据绑定的操作,事件处理的代码都在Activity中,Activity既像View又像Controller(MVVP架构中包括数据绑定),导致Activity中职责太重,耦合度大.修改和维护起来非常麻烦. 2.MV

随机推荐