Android MVVM+coroutine+retrofit+flow+hilt

news2024/11/29 6:26:05

文章目录

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

Android MVVM+coroutine+retrofit+flow+hilt

概述

在这里插入图片描述

代码结构:

在这里插入图片描述

依赖注入层

数据库:

@Module
@InstallIn(SingletonComponent::class)
class DBModule {

    @Singleton
    @Provides
    fun provideDB(application: Application): AppDatabase {
        return AppDatabase.getDatabase(application)
    }

    @Singleton
    @Provides
    fun provideCacheDao(db: AppDatabase): CacheDao {
        return db.cacheDao()
    }
}

网络请求:

@Module
@InstallIn(SingletonComponent::class)
class NetworkModule {

    @Singleton
    @Provides
    fun provideOkHttpClient(): OkHttpClient {
        return HttpManager.okHttpClient
    }

    @Singleton
    @Provides
    fun provideRetrofit(okHttpClient: OkHttpClient): Retrofit {
        return HttpManager.retrofit
    }

    @Singleton
    @Provides
    fun provideLoginApi(retrofit: Retrofit): LoginApi {
        return retrofit.create(LoginApi::class.java)
    }

    @Singleton
    @Provides
    fun provideArticleApi(retrofit: Retrofit): ArticleApi {
        return retrofit.create(ArticleApi::class.java)
    }
}

数据层

open class BaseModel {

    @Inject
    lateinit var cacheHelper: CacheHelper

    fun <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() {

    @Inject
    lateinit var articleApi: ArticleApi

    suspend 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: VB
    protected val mViewBinding get() = _mViewBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        _mViewBinding = createViewBinding()
        setContentView(_mViewBinding.root)
        initViews()
        initData(savedInstanceState)
    }

    abstract fun createViewBinding(): VB

    abstract 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
                }
        }
    }
}

代码下载

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

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

相关文章

springboot -事务管理

事务 概念 事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff0c;这些操作要么同时成功&#xff0c;要么同时失败。 操作 开启事务&#xff1a; start transaction / begin提交事务&#xff1a;commit回滚事务&#xff1a; rollback 注解 Transactional …

网卡bonding绑定

目录 一、概念 1、概述&#xff1a; 二、实验 1、绑定案例&#xff1a; 一、概念 1、概述&#xff1a; 将多个物理网卡进行排列组合&#xff0c;形成逻辑网卡&#xff0c;网卡的高可用 绑定模式 mode0&#xff08;平衡负载模式&#xff09;&#xff1a;平时两块网卡均工…

Hadoop学习笔记(HDP)-Part.18 安装Flink

目录 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 …

作业12.5

1.定义一个基类 Animal&#xff0c;其中有一个虛函数perform&#xff08;)&#xff0c;用于在子类中实现不同的表演行为。 #include <iostream>using namespace std; class Animal { private:int weight; public:Animal(){}Animal(int weight):weight(weight){}virtual …

《形式语言与自动机理论(第4版)》笔记(二)

文章目录 [toc]前导《形式语言与自动机理论&#xff08;第4版&#xff09;》笔记&#xff08;一&#xff09; 第三章&#xff1a;有穷状态自动机3.1|语言的识别3.2|有穷状态自动机即时描述 s e t ( ) set() set()例题问题 1 1 1解答问题 2 2 2解答 3.3|不确定的有穷状态自动机构…

站点可靠性工程SRE最佳实践 -- 黄金监控信号

延迟、流量、错误率、饱和度这四大黄金信号是SRE的最佳实践&#xff0c;可用来帮助SRE团队快速评估系统状态&#xff0c;在异常情况下及时介入&#xff0c;保证系统始终工作在健康状态。原文: Four Golden Signals Of Monitoring: Site Reliability Engineering (SRE) Metrics[…

创建 Python Docker 镜像的完整指南

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com Python和Docker是两个极其流行的技术&#xff0c;结合它们可以创建强大的应用程序。Docker允许将应用程序及其依赖项打包到一个独立的容器中&#xff0c;而Python则提供了丰富的库和工具来开发应用程序。本文将提…

群晖NAS配置之自有服务器ngrok实现内网穿透

群晖NAS配置之自有服务器ngrok实现内网穿透 前言-内网穿透 内网穿透是指通过一种技术让外部网络可以访问到内网的NAS设备&#xff0c;这样即使在不同网络环境下&#xff0c;也能够远程访问和管理NAS设备。以下是一些常见的内网穿透方案&#xff1a; Synology官方提供的Quick…

华盛顿特区警方推荐购买 AirTag防止高端夹克被窃

根据美国媒体 Fox5 报道&#xff0c;近期由于天气变冷&#xff0c;华盛顿特区已发声多起高端 Canada Goose 夹克被窃事件。这些被偷走的加拿大鹅夹克价格从几百到几千美元不等&#xff0c;“Canada Goose”LOGO较为明显&#xff0c;很容易被小偷发现。 对此&#xff0c;警方建…

nodejs+vue+elementui校园演出赞助艺术资源管理系统

系统主要分为系统管理员和学生、校外人员三个部分&#xff0c;系统管理员主要功能包括&#xff1a;首页、个人中心、学生管理、校外人员管理、社团信息管理、校内演出管理、校外商演管理、系统管理&#xff1b;基本上实现了整个基于vue的校园艺术资源管理系统的设计与实现信息管…

SpringBoot3-快速体验

1、pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.…

Linux性能系统学习之监控工具

目录 前言linux性能度量标准监控工具topuptimeps/pstreefreempstatvmstat 前言 在实际产品开发过程中遇到一些莫名其妙的问题&#xff0c;比如swap交换分区随着时间增多影响到系统调用&#xff0c;或CPU占用以及内存的监测等&#xff0c;所以有必要系统了解Linux的性能问题。 …

CUDA简介——For循环并行化

1. 引言 前序博客&#xff1a; CUDA简介——基本概念CUDA简介——编程模式 kernel相关语法定义为&#xff1a; kernel函数定义&#xff0c;与常规C函数定义类似。不同之处在于&#xff0c;有__global__关键字。 为说明符&#xff0c;告诉编译器该函数应编译运行在device上&a…

极客大挑战2023 Reverse wp

文章目录 [toc] shiftjmp点击就送的逆向题幸运数字flower-or-tea小黄鸭mySelfeasymath听说cpp很难&#xff1f;砍树浪漫至死不渝是男人就来扎针ezandroid shiftjmp 64bit的ELF文件&#xff0c;IDA打开 考察花指令去除、将E9 nop掉 EXP&#xff1a; enc [ 0x53, 0x58, 0x41, 0…

面向注解编程—Spring 注解看这一篇就够了(2)

面向注解编程—Spring注解大全&#xff08;AOP篇&#xff09; AOP英文全称&#xff1a;Aspect Oriented Programming&#xff08;面向切面编程、面向方面编程&#xff09;&#xff0c;其实说白 了&#xff0c;面向切面编程就是面向特定方法编程。 AOP的作用&#xff1a;在程序…

【好书推荐】Flutter入门经典

目录 作者简介内容简介文章详解介绍《Flutter入门经典》读者对象《Flutter入门经典》内容要点《Flutter入门经典》内容结构第I部分&#xff1a;Flutter编程基础第II部分&#xff1a;充当媒介的Flutter&#xff1a;具象化一个应用第III部分&#xff1a;创建可用于生产环境的应用…

广州数字孪生赋能工业制造,加速推进制造业数字化转型

广州数字孪生赋能工业制造&#xff0c;加速推进制造业数字化转型。数字孪生系统基于历史数据、实时数据&#xff0c;采用人工智能、大数据分析等新一代信息技术对物理实体的组成、特征、功能和性能进行数字化定义和建模。通过构建在信息世界对物理实体的等价映射&#xff0c;对…

Geodesic in Heat: 一种测地线计算方法

在之前的博客中&#xff0c;我已经介绍过了使用Fast Marching算法计算测地线。Fast Marching的好处是实现简单&#xff0c;方便扩展在点云上。但是缺点是精度不够&#xff0c;求解不平滑。早在2013年&#xff0c;Crane et al. [1]就已经提出利用热流来估算测地距离。我很早就知…

深入理解Java核心技术:Java工程师的实用干货笔记

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 在Java工程师的职业生涯中&#xff0c;深入理解…

使用C语言创建高性能网络爬虫IP池

目录 一、引言 二、IP池的设计 1、需求分析 2、架构设计 3、关键技术 三、IP池的实现 1、存储实现 2、调度实现 3、通信实现 4、异常处理实现 四、代码示例 五、性能优化 六、测试与分析 七、结论 一、引言 随着互联网的快速发展&#xff0c;网络爬虫成为了获取…