Android MVVM+coroutine+retrofit+flow+hilt

本文介绍了如何在Android应用中使用MVVM架构,结合Coroutine进行异步操作,Retrofit进行网络请求,以及Hilt进行依赖注入。详细展示了数据库、网络模块的创建,以及数据层、视图层和模型层的实现和交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

代码下载

为了满足广大Android开发爱好者与从业者的学习需求,我们精心整理并上传了一份全面而实用的Android项目资源包。这份资源包内容丰富,涵盖了从基础知识到实战应用的全方位内容,旨在为开发者们提供一个便捷、高效的学习平台。 一、文件手册 资源包中的文件手册部分,详细记录了Android开发的核心知识点和常用技术。无论是初学者还是有一定经验的开发者,都能从中找到所需的学习资料。手册采用了简洁明了的排版方式,使得查阅更加方便快捷。同时,手册内容深入浅出,既适合新手入门,也能为老手提供有价值的参考。 二、项目实战与练习 为了让学习者能够将理论知识与实践相结合,我们特别准备了项目实战与练习部分。这部分内容包含了多个精心设计的Android项目案例,从需求分析、设计思路到实现过程,都有详细的讲解和代码示例。学习者可以通过实际操作,深入了解Android开发的整个流程,提升自己的实战能力。 此外,我们还提供了一系列练习题,旨在巩固所学知识,检验学习成果。这些练习题既有基础题,也有难度较高的挑战题,适合不同层次的学习者进行练习。 三、Android开发工具集 在Android开发过程中,选择合适的工具能够大大提高开发效率。因此,我们整理了常用的Android开发工具集,包括开发工具、测试工具、性能优化工具等。这些工具都是经过我们精心筛选和测试的,能够帮助开发者们更加高效地进行Android开发工作。 总的来说,这份Android项目资源包是一份不可多得的学习资料,无论你是初学者还是有一定经验的开发者,都能从中受益匪浅。我们希望通过这份资源包,为广大Android开发爱好者与从业者提供一个更加便捷、高效的学习平台,共同推动Android开发领域的发展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值