【问题标题】:In this android-compose codelab why do they pass Lambda instead of navController?在这个 android-compose codelab 中,为什么他们通过 Lambda 而不是 navController?
【发布时间】:2022-11-07 13:08:36
【问题描述】:

为什么android开发人员的这个codelab传递一个“onNextButtonClicked:()->单元”,而不是仅仅传递“navController:NavController,”......看起来更简单......有这个原因吗?

Codelab in github

【问题讨论】:

    标签: android android-jetpack-compose


    【解决方案1】:

    将导航控制器传递到屏幕不是一个好习惯,这是以前的答案之一。

    测试写作: 当你通过回调到最高级别达到你想要的命令时;您现在可以轻松编写测试,并且不需要模拟导航控制器。

    因此,只有通过检查您使用过的回调,您才能确保可组合项功能的正确性。

    考虑以下示例:

    后屏幕

    
    import androidx.compose.foundation.lazy.LazyColumn
    import androidx.compose.foundation.lazy.items
    import androidx.compose.material.Button
    import androidx.compose.material.Text
    import androidx.compose.runtime.Composable
    import androidx.compose.runtime.remember
    
    @Composable
    fun PostScreen(
        navigateToPostDetail: (PostId: PostId) -> Unit
    ) {
        val posts = remember {
            mutableListOf<Post>().apply {
                repeat(10) {
                    add(
                        Post(
                            id = "$it", title = "Title $it"
                        )
                    )
                }
            }
        }
        PostScreenContent(
            posts = posts,
            navigateToPostDetail = navigateToPostDetail
        )
    }
    
    data class Post(
        val id: String, val title: String
    )
    
    @Composable
    internal fun PostScreenContent(
        posts: List<Post>,
        navigateToPostDetail: (PostId: PostId) -> Unit
    ) {
        LazyColumn {
            items(items = posts, key = { item -> item.id }) { item ->
                Text(text = item.title)
                Button(onClick = {
                    navigateToPostDetail(PostId(item.id))
                }
                ) {
                    Text(text = "Navigate To Detail")
                }
            }
        }
    
    }
    
    @JvmInline
    value class PostId(val value: String)
    

    屏幕后测试

    
    import androidx.activity.ComponentActivity
    import androidx.compose.runtime.remember
    import androidx.compose.ui.test.junit4.createAndroidComposeRule
    import org.junit.Rule
    import org.junit.Test
    
    
    internal class PostScreenTest {
        @get:Rule
        val composeTestRule = createAndroidComposeRule<ComponentActivity>()
    
        @Test
        fun clickOnPostItem() {
            var expectedPostId = "your expected id"
            var actualPostId: String
            with(composeTestRule) {
                setContent {
                    val posts = remember {
                        mutableListOf<Post>().apply {
                            repeat(10) {
                                add(
                                    Post(
                                        id = "$it",
                                        title = "Title $it"
                                    )
                                )
                            }
                        }
                    }
                    PostScreenContent(
                        posts = posts,
                        navigateToPostDetail = {
                            actualPostId = it.value
                        }
                    )
                }
                assertThat(actualPostId).isEqualTo(expectedPostId)
            }
        }
    }
    

    但是,如果你想测试整个应用的导航逻辑,测试你的最高层,你使用 NavHost 的地方就足够了。

    【讨论】:

      【解决方案2】:

      这称为状态提升。您可以在official documentation 上阅读更多内容。

      不过,快速回答您的问题:您提到的方式将起作用。但是通过hoisting 状态——也就是说,将可组合的状态移动到可组合之外并将其进一步向上推,通过使可组合stateless 可以使组件更容易重用测试

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多