当前位置: 首页 > article >正文

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
    @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.kler.cn/a/163124.html

相关文章:

  • HBase理论_背景特点及数据单元及与Hive对比
  • 【专题】计算机网络之网络层
  • [ 网络安全介绍 5 ] 为什么要学习网络安全?
  • mac终端使用pytest执行iOS UI自动化测试方法
  • 字节、快手、Vidu“打野”升级,AI视频小步快跑
  • 如何为电子课程创造创意
  • LSTM_预测价格问题_keras_代码实操
  • 喜讯:加速度商城系统全系列产品品牌全新升级为Shopfa
  • Java工程找不到javax.xml.bind.annotation包
  • 【flink番外篇】1、flink的23种常用算子介绍及详细示例(3)-window、distinct、join等
  • STM32 map文件详解
  • Kubernetes(K8s 1.27.x) 快速上手+实践,无废话纯享版
  • running小程序重要技术流程文档
  • 【ELK03】ES 索引的Mapping映射详解、数据类型和settings属性设置
  • 算法:常见的链表算法
  • 插入排序——直接插入排序和希尔排序(C语言实现)
  • 如何进行更好的面试回复之缓存函数在项目中的性能优化?
  • Advanced Renamer
  • 利用R语言heatmap.2函数进行聚类并画热图
  • Shell脚本如何使用 for 循环、while 循环、break 跳出循环和 continue 结束本次循环
  • Vue学习笔记-Vue3中的计算属性与监视属性
  • 【数据结构】拆分详解 - 二叉树的链式存储结构
  • 消费升级:无人零售的崛起与优势
  • 【MATLAB源码-第97期】基于matlab的能量谷优化算法(EVO)机器人栅格路径规划,输出做短路径图和适应度曲线。
  • git操作:使用vscode集成
  • Spring Cloud Gateway中对admin端点进行认证