Android MVVM+coroutine+retrofit+flow+hilt
文章目录
- Android MVVM+coroutine+retrofit+flow+hilt
- 概述
- 依赖注入层
- 数据层
- 视图层
- 模型视图层
- 代码下载
Android MVVM+coroutine+retrofit+flow+hilt
概述

代码结构:

依赖注入层
数据库:
@Module
@InstallIn(SingletonComponent::class)
class DBModule {@Singleton@Providesfun provideDB(application: Application): AppDatabase {return AppDatabase.getDatabase(application)}@Singleton@Providesfun provideCacheDao(db: AppDatabase): CacheDao {return db.cacheDao()}
}
网络请求:
@Module
@InstallIn(SingletonComponent::class)
class NetworkModule {@Singleton@Providesfun provideOkHttpClient(): OkHttpClient {return HttpManager.okHttpClient}@Singleton@Providesfun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {return HttpManager.retrofit}@Singleton@Providesfun provideLoginApi(retrofit: Retrofit): LoginApi {return retrofit.create(LoginApi::class.java)}@Singleton@Providesfun provideArticleApi(retrofit: Retrofit): ArticleApi {return retrofit.create(ArticleApi::class.java)}
}
数据层
open class BaseModel {@Injectlateinit var cacheHelper: CacheHelperfun <T> requestForResult(block: suspend () -> BaseResponse<T>): Flow<ResultState<T>> {return flow<ResultState<T>> {val response = block()if (response.isSuccessful()) {emit(ResultState.Success(response.data!!))} else {val serverException = ServerException(response.errorCode, response.errorMsg)val e = ExceptionHandler.handleException(serverException)emit(ResultState.Error(e, e.displayMessage))}}.flowOn(Dispatchers.IO).catch {val e = ExceptionHandler.handleException(it)emit(ResultState.Error(e, e.displayMessage))}}suspend fun <T> requestForResult(cacheName: String,cacheBlock: () -> T?,block: suspend () -> BaseResponse<T>): Flow<ResultState<T>> {return flow {val cacheData = cacheBlock()cacheData?.let {emit(ResultState.Success(cacheData, true))}val response = block()if (response.isSuccessful()) {cacheHelper.saveCache(cacheName, response.data!!)emit(ResultState.Success(response.data, false))} else {val serverException = ServerException(response.errorCode, response.errorMsg)val e = ExceptionHandler.handleException(serverException)emit(ResultState.Error(e, e.displayMessage))}}.flowOn(Dispatchers.IO).catch {val e = ExceptionHandler.handleException(it)emit(ResultState.Error(e, e.displayMessage))}}
}
class ArticleModel @Inject constructor() : BaseModel() {@Injectlateinit var articleApi: ArticleApisuspend fun getArticleList(): Flow<ResultState<ArrayList<ArticleBean>>> {val cacheName = "article_list"return requestForResult(cacheName, {cacheHelper.getCache<ArrayList<ArticleBean>>(cacheName, object : TypeToken<ArrayList<ArticleBean>>() {}.type)}, {articleApi.getArticleList()})}
}
视图层
abstract class BaseActivity<VB : ViewBinding> : AppCompatActivity() {private lateinit var _mViewBinding: VBprotected val mViewBinding get() = _mViewBindingoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)_mViewBinding = createViewBinding()setContentView(_mViewBinding.root)initViews()initData(savedInstanceState)}abstract fun createViewBinding(): VBabstract fun initViews()abstract fun initData(savedInstanceState: Bundle?)
}
@AndroidEntryPoint
class ArticleListActivity : BaseActivity<ActivityArticleListBinding>() {private val mList = arrayListOf<ArticleBean>()private val articleListViewModel by viewModels<ArticleViewModel>()private val progressDialog: ProgressDialog by lazy {ProgressDialog(this).apply {setMessage("加载中")}}override fun createViewBinding(): ActivityArticleListBinding {return ActivityArticleListBinding.inflate(layoutInflater)}override fun initViews() {}override fun initData(savedInstanceState: Bundle?) {mViewBinding.rvArticleList.adapter = ArticleAdapter(this, mList)mViewBinding.btnGetArticleList.setOnClickListener {getArticleList()}observe()}private fun getArticleList() {articleListViewModel.getArticleList()}private fun observe() {lifecycleScope.launch {repeatOnLifecycle(Lifecycle.State.RESUMED) {articleListViewModel.articleFlow.collect {when (it) {is ResultState.Loading -> showLoading()is ResultState.Error -> {showToast(it.message)hideLoading()}is ResultState.Success -> {hideLoading()updateUI(it.data)}}}}}}private fun updateUI(list: ArrayList<ArticleBean>?) {mList.clear()if (list != null) {mList.addAll(list)}mViewBinding.rvArticleList.adapter!!.notifyDataSetChanged()}private fun showLoading() {progressDialog.show()}private fun hideLoading() {progressDialog.hide()}
}
模型视图层
open class BaseViewModel : ViewModel() {fun launchMain(block: suspend CoroutineScope.() -> Unit) {viewModelScope.launch(Dispatchers.Main) {block()}}fun launchIO(block: suspend CoroutineScope.() -> Unit) {viewModelScope.launch(Dispatchers.IO) {block()}}fun launchDefault(block: suspend CoroutineScope.() -> Unit) {viewModelScope.launch(Dispatchers.Default) {block()}}
}
@HiltViewModel
class ArticleViewModel @Inject constructor(private val articleModel: ArticleModel
) : BaseViewModel() {private val _articleFlow =MutableStateFlow<ResultState<ArrayList<ArticleBean>>>(ResultState.None)val articleFlow get() = _articleFlow.asStateFlow()fun getArticleList() {launchIO {articleModel.getArticleList().onStart {_articleFlow.value = ResultState.Loading}.collect {_articleFlow.value = it}}}
}
代码下载
相关文章:
Android MVVM+coroutine+retrofit+flow+hilt
文章目录 Android MVVMcoroutineretrofitflowhilt概述依赖注入层数据层视图层模型视图层代码下载 Android MVVMcoroutineretrofitflowhilt 概述 代码结构: 依赖注入层 数据库: Module InstallIn(SingletonComponent::class) class DBModule {Singleto…...
elasticsearch副本和分片
1.文档冲突 当我们使用index API更新文档,可以一次性读取 修改索引副本 rootes-node3:~# curl -XPUT http://192.168.1.136:9200/es-syslog-2023.08.26/_settings -H "Content-Type: application/json" -d { > "settings": { > …...
【Python】zip
Python中的zip()函数可以将多个可迭代对象打包成一个元组序列,然后返回这些元组序列组成的迭代器。zip()函数的语法如下: zip(*iterables)其中,iterables是可迭代对象,可以是多个,也可以是一个。zip()函数将返回一个迭…...
西安安泰——ATA-1220E宽带放大器
ATA-1220E宽带放大器简介 ATA-1220E是一款可放大交直流信号的差分通道宽带放大器。其最大输出电压 60Vp-p(30Vp),最大输出电流1Ap(>50Hz)。电压增益数控可调,一键保存设置,提供了方便简洁的操作选择,可…...
数据结构和算法专题---4、限流算法与应用
本章我们会对限流算法做个简单介绍,包括常用的限流算法(计数器、漏桶算法、令牌桶案发、滑动窗口)的概述、实现方式、典型场景做个说明。 什么是限流算法 限流是对系统的一种保护措施。即限制流量请求的频率(每秒处理多少个请求…...
亚信安慧AntDB受邀分享核心业务系统全域数据库替换实践
近日,亚信安慧AntDB数据库凭借丰富的核心业务系统升级替换能力和经验,受邀参与IT168组织的第三期“国产软硬件升级替换之路”的直播沙龙。 亚信安慧AntDB数据库相关负责人发表《基于AntDB的CRM全域数据库替换实践》的精彩演讲,通过通信行业率…...
1.uniapp基础
1.uniapp基础 官方文档:uni-app官网 1.1开发工具 (1)工具: HBuilderX HBuilderX-高效极客技巧 1.2 新建项目 (1) 文件》新建项目 (2)选择相应的配置信息,填写项目根路…...
typescript中的策略模式
typescript中的策略模式 当我们需要以整洁、易于维护和易于调试的方式构建应用程序时,使用设计模式是一种非常好的方式。 在本文中,我们的目标是阐明如何将策略模式无缝地集成到我们的应用程序中。如果我们熟悉依赖性注入,可能会发现策略模…...
Hadoop学习笔记(HDP)-Part.16 安装HBase
目录 Part.01 关于HDP Part.02 核心组件原理 Part.03 资源规划 Part.04 基础环境配置 Part.05 Yum源配置 Part.06 安装OracleJDK Part.07 安装MySQL Part.08 部署Ambari集群 Part.09 安装OpenLDAP Part.10 创建集群 Part.11 安装Kerberos Part.12 安装HDFS Part.13 安装Ranger …...
C语言练习记录(蓝桥杯练习)(小蓝数点)
目录 小蓝数点 第一题程序的输出结果是?: 第二题下面代码的执行结果是什么?: 第三题下面代码的执行结果是什么?: 第四题关于关系操作符说法错误的是?: 第五题对于下面代码段,y的值为? 第六题sum 21 …...
RPG项目01_层级设置
基于“RPG项目01_UI面板Game”, 找到狼人 添加组件,让狼人一定区域自动跟随主角进行攻击 解释:【烘培蓝色】因为如果什么都不做就会被烘培成蓝色对应的功能就是 可修改区域功能 当将区域设置成不可行走状态,则不为蓝色 烘培&…...
相关基础知识
本文引注: https://zhuanlan.zhihu.com/p/447221519 1.方差 2.自协方差矩阵 3.自相关矩阵 4.互协方差矩阵 5.互相关矩阵 6.相关系数 7.自相关函数、自协方差函数与功率谱密度 8.互相关函数、互协方差函数与互功率谱密度...
基于单片机的智能健康监测手环的设计
目 录 1 绪论... 2 1.1 引言... 2 1.2 智能手环的国内外研究现状... 2 1.3 课题的研究意义... 3 1.4 本文的研究内容和章节安排... 4 2 智能手环系统设计方案... 5 2.1 系统总体设计方案... 5 2.2 主芯片选择... 5 2.3 显示方案的选择... 6 2.4 倾角传感器的选择... 6 2.5 心率…...
boost-字符串处理-判断-查找-裁剪-删除-替换-分割-合并
文章目录 1.判断1.1.equals1.2.all1.3.starts_with1.4.ends_with1.5.contains 2.大小写转换3.字符串删除4.字符串替换5.字符串查找6.字符串修剪7.字符串分割8.字符串合并9.总结 1.判断 判别式函数和分类函数大多数都是以is_开头,这些函数如下: 判别式函…...
Django 开发 web 后端,好用过 SpringBoot ?
基础语法 Django(Python):以简洁和直观著称。它允许更快的开发速度,特别适合快速迭代的项目。例如,一个简单的视图函数: from django.http import HttpResponsedef hello_world(request):return HttpRespon…...
【矩阵】54.螺旋矩阵(顺时针打印矩形元素)
题目 class Solution {public List<Integer> spiralOrder(int[][] matrix) {int m matrix.length, n matrix[0].length;int leftUpM 0, leftUpN 0, rightDownM m - 1, rightDownN n - 1;List<Integer> res new ArrayList<>();while (leftUpM < ri…...
【数据中台】开源项目(5)-Amoro
介绍 Amoro is a Lakehouse management system built on open data lake formats. Working with compute engines including Flink, Spark, and Trino, Amoro brings pluggable and self-managed features for Lakehouse to provide out-of-the-box data warehouse experience,…...
_WorldSpaceLightPos0的含义 UNITY SHADER
_WorldSpaceLightPos0 为当前平行光的方向,方向是从光源到照射的方向。 因此,如果要算法线和平行光之间的夹角, 则需要首先将归一化的_WorldSpaceLightPos0去负数。这样才能继续去计算。 也就是: fixed3 reflectdirnormalize…...
iOS不越狱自动挂机
自动挂机在电脑上或者安卓手机上都相对容易,而在不越狱的iOS设备上还是有点难度的。 此方法不是我原创,详情见: 【苹果党福音,ios也能用的挂机脚本】 https://www.bilibili.com/video/BV1sv4y1P7TL/?share_sourcecopy_web&v…...
智能优化算法应用:基于鼠群算法无线传感器网络(WSN)覆盖优化 - 附代码
智能优化算法应用:基于鼠群算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于鼠群算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.鼠群算法4.实验参数设定5.算法结果6.参考文献7.MATLAB…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
elementUI点击浏览table所选行数据查看文档
项目场景: table按照要求特定的数据变成按钮可以点击 解决方案: <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...
ui框架-文件列表展示
ui框架-文件列表展示 介绍 UI框架的文件列表展示组件,可以展示文件夹,支持列表展示和图标展示模式。组件提供了丰富的功能和可配置选项,适用于文件管理、文件上传等场景。 功能特性 支持列表模式和网格模式的切换展示支持文件和文件夹的层…...
