安卓MVI架构真的来了?动手试着封装吧(三)上

简介: 安卓MVI架构真的来了?动手试着封装吧(三)

本篇内容主要为UI层如何订阅改造之后的viewModel的事件流和状态流


UI状态流的订阅


  为什么要单独写一篇如何订阅Flow(流)的文章呢,首先我们回顾一下官方开发者文档中提供的推荐写法。(代码较多,每一行代码的作用已经用注释写明)


class NewsActivity : AppCompatActivity() {
    private val viewModel: NewsViewModel by viewModels()
    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        //开启协程
        lifecycleScope.launch {
            //控制订阅的生命周期(在UI不可见时取消订阅避免性能浪费)
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.uiState
                    //只关注整个状态流中的某个元素
                    .map { it.isFetchingArticles }
                    //防抖,防止其他元素更新导致自身更新
                    .distinctUntilChanged()
                    //收集最终元素
                    .collect { progressBar.isVisible = it }
            }
        }
    }
}

  可见,仅仅是收集一个元素,我们就需要反复书写7行代码,除了我要收集什么元素收集元素之后干什么以外,其余的代码均为模板代码,因此消除这些模板代码是第一业务,毕竟谁也不希望项目中存在一大堆复制粘贴的代码。

  因此,我们的目标是实现一套这样的代码。


//绑定生命周期
viewModel.container.run{
    uiStateFlow.collectState(某个lifecycleOwner) {
        //收集UiState中的某个元素
        collectPartial(某个元素) {
            //做一些事情
        }
        //收集UiState中的某个元素
        collectPartial(某个元素) {
            //做一些事情
        }
        //...收集其余的元素
    }
}

  既然我们是在Flow上面新增逻辑,那么肯定是需要用到kotlin的扩展函数,因此我们给Flow增加一个扩展函数,同时指定必须是UiState的Flow(避免污染到其他非UiState Flow的代码)


fun <T : UiState> Flow<T>.collectState(
    //生命周期持有者,一般是Activity,Fragment之类的
    lifecycleOwner: LifecycleOwner,
    //repeatOnLifecycle方法用
    state: Lifecycle.State = Lifecycle.State.STARTED,
    //State收集器(关键元素),下文会谈到
    action: StateCollector<T>.() -> Unit
) {
    //传递给State收集器,用于开启多个collectPartial()方法
    StateCollector(this@collectState, lifecycleOwner, state).action()
}

  此处并没有给出StateCollector的源码,也许你会很好奇他的作用,其实它的作用并不复杂,只是将collectState()方法中的参数打包在一起,然后通过StateCollector来调用collectPartial()方法来收集UiState中的某个元素。

  此时最大的问题来了,如何在方法中去指定一个Class中的某个元素呢?(下面提供一个data class供读者思考)


data class FriendUiState(
    //朋友列表
    val friendBeanList: List<FriendBean> = emptyList(),
    //是否刷新中
    val refreshing: Boolean = false,
    //是否加载更多
    val loadMore: Boolean = false,
    //是否还有更多数据
    val noMoreData: Boolean = false,
) : UiState

image.png

  答案并不复杂,我们用反射即可,通过kt强大的反射机制,我们可以实现伪代码中的效果。关于kt的反射本文中并不会赘述,你可以通过掘金或者其他网站去自学kt的反射。在继续读下文之前,笔者假设你已经会了kt的反射(至少能看懂代码)

  我们来看看刚才没有给出来的StateCollector的代码


class StateCollector<T : UiState>(
    private val flow: Flow<T>,
    private val lifecycleOwner: LifecycleOwner,
    private val state: Lifecycle.State,
) {
    fun <A> collectPartial(
        prop1: KProperty1<T, A>,
        action: (A) -> Unit
    ) {
        //lifecycleOwner利用开启协程
        lifecycleOwner.lifecycleScope.launch {
            //控制订阅的生命周期
            lifecycleOwner.repeatOnLifecycle(state) {
                    //只关注整个状态流中的某个元素(重点!利用反射机制找出需要的元素)
                    flow.map { prop1.get(it) }
                    //防抖,防止其他元素更新导致自身更新
                    .distinctUntilChanged()
                    //收集元素
                    .collect { partialState ->
                        action(partialState)
                    }
            }
        }
    }

  可见,StateCollector的作用只有1点:消除模板代码。将需要反复重写的逻辑封装在一个收集器的内部,使用了StateCollector之后,我们重新回到最初的伪代码中。


//伪代码
viewModel.container.run{
    uiStateFlow.collectState(某个lifecycleOwner) {
        //收集UiState中的某个元素
        collectPartial(某个元素) {
            //做一些事情
        }
        //收集UiState中的某个元素
        collectPartial(某个元素) {
            //做一些事情
        }
        //...收集其余的元素
    }
}
//封装后的代码
viewModel.container.run {
    uiStateFlow.collectState(this@FriendsActivity2) {
        collectPartial(FriendUiState::friendBeanList) {
            //do someThing
        }
        collectPartial(FriendUiState::refreshing) { refreshing ->
            //do someThing
        }
        collectPartial(FriendUiState::loadMore) { loadMore ->
            //do someThing
        }
        collectPartial(FriendUiState::noMoreData) { noMoreData ->
            //do someThing
        }
    }
}

经过封装后的代码减少了非常多的模板代码,在绑定了lifecycleOwner之后只需要关注两件事:

  1. 收集谁
  2. 收集之后干啥

目录
打赏
0
0
0
0
1
分享
相关文章
深入探索Android与iOS的差异:从系统架构到用户体验
在当今的智能手机市场中,Android和iOS无疑是最受欢迎的两大操作系统。本文旨在探讨这两个平台之间的主要差异,包括它们的系统架构、开发环境、安全性、以及用户体验等方面。通过对比分析,我们可以更好地理解为何不同的用户群体可能会偏好其中一个平台,以及这些偏好背后的技术原因。
深入探索iOS与Android操作系统的架构差异及其对应用开发的影响
在当今数字化时代,移动设备已经成为我们日常生活和工作不可或缺的一部分。其中,iOS和Android作为全球最流行的两大移动操作系统,各自拥有独特的系统架构和设计理念。本文将深入探讨iOS与Android的系统架构差异,并分析这些差异如何影响应用开发者的开发策略和用户体验设计。通过对两者的比较,我们可以更好地理解它们各自的优势和局限性,从而为开发者提供有价值的见解,帮助他们在这两个平台上开发出更高效、更符合用户需求的应用。
android做中大型项目完美的架构模式是什么?是MVVM吗?如果不是,是什么?
android做中大型项目完美的架构模式是什么?是MVVM吗?如果不是,是什么?
179 2
Android MVVM架构模式下如何避免内存泄漏
Android采用MVVM架构开发项目,如何避免内存泄漏风险?怎样避免内存泄漏?
145 1
深入探索Android系统架构与性能优化
本文旨在为读者提供一个全面的视角,以理解Android系统的架构及其关键组件。我们将探讨Android的发展历程、核心特性以及如何通过有效的策略来提升应用的性能和用户体验。本文不包含常规的技术细节,而是聚焦于系统架构层面的深入分析,以及针对开发者的实际优化建议。
122 21
深入探索Android系统架构:从内核到应用层的全面解析
本文旨在为读者提供一份详尽的Android系统架构分析,从底层的Linux内核到顶层的应用程序框架。我们将探讨Android系统的模块化设计、各层之间的交互机制以及它们如何共同协作以支持丰富多样的应用生态。通过本篇文章,开发者和爱好者可以更深入理解Android平台的工作原理,从而优化开发流程和提升应用性能。
深入探索iOS与Android系统架构差异及其对开发者的影响
本文旨在通过对比分析iOS和Android两大移动操作系统的系统架构,探讨它们在设计理念、技术实现及开发者生态方面的差异。不同于常规摘要仅概述内容要点,本摘要将简要触及核心议题,为读者提供对两大平台架构特点的宏观理解,铺垫
深入探索Android与iOS操作系统的架构差异
本文旨在对比分析Android和iOS两大主流移动操作系统在架构设计上的根本差异。通过详细解读两者的系统架构、开发环境、以及安全性等方面,揭示它们各自的特点及优势,为开发者选择合适的平台提供参考。
深入探索Android系统架构:从Linux内核到应用层
本文将带领读者深入了解Android操作系统的复杂架构,从其基于Linux的内核到丰富多彩的应用层。我们将探讨Android的各个关键组件,包括硬件抽象层(HAL)、运行时环境、以及核心库等,揭示它们如何协同工作以支持广泛的设备和应用。通过本文,您将对Android系统的工作原理有一个全面的认识,理解其如何平衡开放性与安全性,以及如何在多样化的设备上提供一致的用户体验。
深入探讨Android与iOS的系统架构差异
本文旨在通过对比分析Android和iOS两大移动操作系统的系统架构,揭示它们在设计理念、安全性、应用生态及开发环境等方面的显著差异。我们将从底层架构出发,逐步剖析至用户界面层面,为开发者和科技爱好者提供一份详尽的技术参考。
91 1

热门文章

最新文章

  • 1
    即时通讯安全篇(一):正确地理解和使用Android端加密算法
    16
  • 2
    escrcpy:【技术党必看】Android开发,Escrcpy 让你无线投屏新体验!图形界面掌控 Android,30-120fps 超流畅!🔥
    35
  • 3
    【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
    69
  • 4
    Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件
    34
  • 5
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    50
  • 6
    Android历史版本与APK文件结构
    141
  • 7
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    42
  • 8
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
    36
  • 9
    APP-国内主流安卓商店-应用市场-鸿蒙商店上架之必备前提·全国公安安全信息评估报告如何申请-需要安全评估报告的资料是哪些-优雅草卓伊凡全程操作
    63
  • 10
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
    45