Android数据缓存框架 - 内存数据载体从LiveData到StateFlow

2024-05-24 06:44

本文主要是介绍Android数据缓存框架 - 内存数据载体从LiveData到StateFlow,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

引言:所有成功者的背后,都有一份艰苦的历程,不要只看到了人前的风光,而低估了他们背后所付出的努力。

随着flow到流行度越来越高,有开发者呼吁我使用flow,于是我就如你们所愿,新增了StateFlow作为新的数据载体。当然你仍然可以使用旧版本的LiveData,代码写法略微不同罢了。如果对我的dcache框架设计不是很理解的小伙伴,可以看我的专栏其他文章。

为什么推荐使用StateFlow

如果你非要问我为什么要使用StateFlow?我可以告诉你,因为可以装逼,哈哈,开个玩笑。新技术的流行必然有一部分炒作的部分,但也肯定是有其改进的地方的。要讲StateFlow,就不得不从flow开始说起。flow是属于kotlin语言范畴的,你可以把它当成kotlin协程的一个API。没错,kotlin语言的野心就是要做跨平台的语言,答案就在这里,LiveData是android的API,而SharedFlow与StateFlow直接就是Kotlin编程语言级别的,代码复用性更好。

LiveData和StateFlow使用对比

以列表数据模式的Repository为例。从2.1.5开始@Repository注解拆分成了@Repository注解和@ListRepository,所以2.1.4版本你应该使用@Repository注解,而如果说,你使用的是2.1.5及以上版本的dcache库,要使用@ListRepository注解。由于StateFlow在2.2.0版本才开始支持,所以自然要使用@ListRepository注解。
先看StateFlow的写法。

override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)// 此处省略代码若干行lifecycleScope.launchWhenCreated {repository.getListFlowData().collect {adapter.setTemperatures(it)}}
}

不要忘了使用协程作用域。
然后我们调用fetchListData()。

repository.fetchListData(listener = object : OnLoadStateListener {override fun onLoad(state: Int) {Log.d("WeatherActivity", "数据是否加载成功:${state==0}")}
}, description = null)

加载状态监听接口和描述信息可以传null。这个抓取数据方法一经调用,collect代码块就会刷新数据。由于fetchListData()天然就返回的StateFlow,所以你并不一定要分为两步观察数据。而如果你要分为两步,则调用getListFlowData()或getFlowData()。
再看原来LiveData的写法,这次我们不用list模式的Repository,如果要使用,直接配置@Repository注解。

minutelyRepository.latlng = "116.407526,39.90403"
minutelyRepository.fetchData("按分钟统计天气").observe(this, Observer {it?.apply {tvCacheMinutely.text = "minutely:${toString()}\n"}
})

很明显,fetchData()返回LiveData,直接调用observe()进行数据的观察。简单总结下,API的设计在调用层面具有相似性,所以,无论你使用的是LiveData为数据载体的Repository还是StateFlow的,都是调用fetchData()或fetchListData()更新缓存数据,框架内部自动帮你缓存到数据库,同时常驻在内存并递送给UI层刷新界面。所以你可以专心开发你的业务逻辑,这是不是很棒?

package com.example.dcache.repositoryimport android.content.Context
import com.example.dcache.biz.weather.WeatherService
import com.example.dcache.model.WeatherModel
import dora.cache.data.fetcher.OnLoadStateListener
import dora.cache.repository.DoraDatabaseCacheRepository
import dora.cache.repository.Repository
import dora.http.DoraCallback
import dora.http.retrofit.RetrofitManager@Repository
class WeatherRepository(context: Context) : DoraDatabaseCacheRepository<WeatherModel>(context) {var latlng: String = ""override fun onLoadFromNetwork(callback: DoraCallback<WeatherModel>,listener: OnLoadStateListener?) {RetrofitManager.getService(WeatherService::class.java).getWeather(latlng).enqueue(callback)}
}

最后简单复习一下Repository的写法。详细Demo代码https://github.com/dora4/DoraCacheSample 。

框架设计的变化

这是StateFlow的。

/*** 用于网络数据抓取。*/
interface IFlowDataFetcher<M> {/*** 清空flow data的数据。*/fun clearData()/*** 抓取数据的回调。*/fun callback(): DoraCallback<M>/*** 开始抓取数据。*/fun fetchData(description: String?, listener: OnLoadStateListener? = OnLoadStateListenerImpl()): StateFlow<M?>/*** 获取flow data。*/fun getFlowData(): StateFlow<M?>
}

这是LiveData的。

package dora.cache.data.fetcherimport androidx.lifecycle.LiveData
import dora.http.DoraCallback/*** 用于网络数据抓取。*/
interface IDataFetcher<M> {/*** 清空livedata的数据。*/fun clearData()/*** 抓取数据的回调。*/fun callback(): DoraCallback<M>/*** 开始抓取数据。*/fun fetchData(description: String?, listener: OnLoadStateListener? = OnLoadStateListenerImpl()): LiveData<M?>/*** 获取livedata。*/fun getLiveData(): LiveData<M?>
}

是不是没啥变化?对的,这就是架构设计的魅力所在。前期架构设计比较到位,所以只需要遵循开闭原则。对扩展开放,对修改关闭。
截屏2024-01-07 17.31.22.png
原先继承BaseRepository的,现在继承BaseFlowRepository的。名字有带Flow单词的,就是StateFlow的。

开源框架支持

笔者写框架和文档不容易,希望你的支持。你的支持是我改进优化最大的动力!

数据缓存dcache框架 https://github.com/dora4/dcache-android

dora框架的开发插件 https://github.com/dora4/dora-studio-plugin

dora框架 https://github.com/dora4/dora

这篇关于Android数据缓存框架 - 内存数据载体从LiveData到StateFlow的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/997669

相关文章

使用Python开发一个Ditto剪贴板数据导出工具

《使用Python开发一个Ditto剪贴板数据导出工具》在日常工作中,我们经常需要处理大量的剪贴板数据,下面将介绍如何使用Python的wxPython库开发一个图形化工具,实现从Ditto数据库中读... 目录前言运行结果项目需求分析技术选型核心功能实现1. Ditto数据库结构分析2. 数据库自动定位3

pandas数据的合并concat()和merge()方式

《pandas数据的合并concat()和merge()方式》Pandas中concat沿轴合并数据框(行或列),merge基于键连接(内/外/左/右),concat用于纵向或横向拼接,merge用于... 目录concat() 轴向连接合并(1) join='outer',axis=0(2)join='o

批量导入txt数据到的redis过程

《批量导入txt数据到的redis过程》用户通过将Redis命令逐行写入txt文件,利用管道模式运行客户端,成功执行批量删除以Product*匹配的Key操作,提高了数据清理效率... 目录批量导入txt数据到Redisjs把redis命令按一条 一行写到txt中管道命令运行redis客户端成功了批量删除k

SpringBoot多环境配置数据读取方式

《SpringBoot多环境配置数据读取方式》SpringBoot通过环境隔离机制,支持properties/yaml/yml多格式配置,结合@Value、Environment和@Configura... 目录一、多环境配置的核心思路二、3种配置文件格式详解2.1 properties格式(传统格式)1.

MySQL 内存使用率常用分析语句

《MySQL内存使用率常用分析语句》用户整理了MySQL内存占用过高的分析方法,涵盖操作系统层确认及数据库层bufferpool、内存模块差值、线程状态、performance_schema性能数据... 目录一、 OS层二、 DB层1. 全局情况2. 内存占js用详情最近连续遇到mysql内存占用过高导致

解决pandas无法读取csv文件数据的问题

《解决pandas无法读取csv文件数据的问题》本文讲述作者用Pandas读取CSV文件时因参数设置不当导致数据错位,通过调整delimiter和on_bad_lines参数最终解决问题,并强调正确参... 目录一、前言二、问题复现1. 问题2. 通过 on_bad_lines=‘warn’ 跳过异常数据3

Android Paging 分页加载库使用实践

《AndroidPaging分页加载库使用实践》AndroidPaging库是Jetpack组件的一部分,它提供了一套完整的解决方案来处理大型数据集的分页加载,本文将深入探讨Paging库... 目录前言一、Paging 库概述二、Paging 3 核心组件1. PagingSource2. Pager3.

最新Spring Security的基于内存用户认证方式

《最新SpringSecurity的基于内存用户认证方式》本文讲解SpringSecurity内存认证配置,适用于开发、测试等场景,通过代码创建用户及权限管理,支持密码加密,虽简单但不持久化,生产环... 目录1. 前言2. 因何选择内存认证?3. 基础配置实战❶ 创建Spring Security配置文件

Python Web框架Flask、Streamlit、FastAPI示例详解

《PythonWeb框架Flask、Streamlit、FastAPI示例详解》本文对比分析了Flask、Streamlit和FastAPI三大PythonWeb框架:Flask轻量灵活适合传统应用... 目录概述Flask详解Flask简介安装和基础配置核心概念路由和视图模板系统数据库集成实际示例Stre

C#监听txt文档获取新数据方式

《C#监听txt文档获取新数据方式》文章介绍通过监听txt文件获取最新数据,并实现开机自启动、禁用窗口关闭按钮、阻止Ctrl+C中断及防止程序退出等功能,代码整合于主函数中,供参考学习... 目录前言一、监听txt文档增加数据二、其他功能1. 设置开机自启动2. 禁止控制台窗口关闭按钮3. 阻止Ctrl +