美文网首页
实施 Jetpack Compose + Orbit MVI

实施 Jetpack Compose + Orbit MVI

作者: 蜗牛是不是牛 | 来源:发表于2022-08-02 15:33 被阅读0次

    我用Jetpack Compose+Orbit MVI创建了一个神奇宝贝图书馆应用程序。Orbit MVI易于使用,请尝试。

    链接

    此示例源代码

    关于Jetpack Compose

    关于 Orbit MVI

    特征

    • 管理神奇宝贝数据。
    • 在列表中显示多个神奇宝贝。
    • 显示神奇宝贝的详细信息。

    建筑风格

    此应用程序架构基于 MVVM + Repository 模式。但是视图状态管理使用 MVI,因为引入了 Jetpack Compose 和 Orbit MVI。

    模块

    该应用程序由多模块结构组成。共有三个模块,每个模块的作用如下图所述。

    姓名 内容
    应用程序 存储 View 和 ViewModel 以管理视图状态。
    领域 存储 UseCase 以处理业务逻辑。
    数据 Store Repository 和 Dao 来管理 Pokémon 数据库。

    图书馆

    此应用程序由底部图中的库创建。

    姓名 关联
    Koin https://insert-koin.io
    Jetpack Compose https://developer.android.com/jetpack/compose
    导航组合 https://developer.android.com/jetpack/compose/navigation
    Orbit MVI https://orbit-mvi.org
    Coil https://coil-kt.github.io/coil/
    Room https://developer.android.com/training/data-storage/room?hl=ja
    Kotlin 序列化 https://github.com/Kotlin/kotlinx.serialization
    口袋妖怪Pokedex https://github.com/Biuni/PokemonGO-Pokedex

    UI 的数据流(UI 状态管理)

    此应用程序数据流是无方向的,如下图所示。

    1. MVI View 将 Action(intent) 发送到 MVI Model。
    2. MVI 模型在收到 Action 时执行 UseCase
    3. UseCase 访问 Repository 以获取 Pokémon Data。
    4. UseCase 将 Pokémon 数据返回给 MVI 模型。
    5. MVI 模型从神奇宝贝数据创建新状态。
    6. MVI 模型将创建的新状态或新事件发送到 MVI 视图。

    此应用程序数据流由 Orbit MVI 实现。(有关如何使用 Orbit MVI 创建 MVI 视图或 MVI 模型的更多信息,请查看此处。)

    MVI模型

    data class InitState(
        val status: UiStatus? = null
    )
    
    sealed class InitSideEffect {
        object Completed : InitSideEffect()
    }
    
    class InitViewModel(
        private val fetchAllPokemonUseCase: FetchAllPokemonUseCase
    ) : ContainerHost<InitState, InitSideEffect>, ViewModel() {
        override val container = container<InitState, InitSideEffect>(
            InitState()
        )
    
        init {
            fetchData()
        }
    
        fun retry() {
            if (container.stateFlow.value.status != UiStatus.Loading) {
                fetchData()
            }
        }
    
        private fun fetchData() {
            intent {
                reduce { state.copy(status = UiStatus.Loading) }
                if (fetchAllPokemonUseCase()) {
                    reduce { state.copy(status = UiStatus.Success) }
                    postSideEffect(InitSideEffect.Completed)
                } else {
                    reduce { state.copy(status = UiStatus.Failed()) }
                }
            }
        }
    }
    
    

    MVI 视图

    @Composable
    fun InitPage(
        viewModel: InitViewModel,
        onCompleted: () -> Unit
    ) {
        val state by viewModel.container.stateFlow.collectAsState()
    
        LaunchedEffect(viewModel) {
            viewModel.container.sideEffectFlow.collect {
                when (it) {
                    is InitSideEffect.Completed -> onCompleted()
                }
            }
        }
    
        Scaffold {
            Box(modifier = Modifier.fillMaxSize()) {
                when (state.status) {
                    UiStatus.Loading -> {
                        DownloadingMessage(
                            modifier = Modifier
                                .wrapContentSize()
                                .align(Alignment.Center)
                        )
                    }
                    is UiStatus.Failed -> {
                        DownloadRetryMessage(
                            onRetry = { viewModel.retry() },
                            modifier = Modifier
                                .wrapContentSize()
                                .align(Alignment.Center)
                        )
                    }
                    UiStatus.Success -> Unit
                }
            }
        }
    }
    

    链接:https://dev.to/kaleidot725/implementaing-jetpack-compose-orbit-mvi-3gea

    相关文章

      网友评论

          本文标题:实施 Jetpack Compose + Orbit MVI

          本文链接:https://www.haomeiwen.com/subject/dhzswrtx.html