首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Jetpack组合:如何检测TabRow在HorizontalPager中何时可见并调用ViewModel函数?

Jetpack组合:如何检测TabRow在HorizontalPager中何时可见并调用ViewModel函数?
EN

Stack Overflow用户
提问于 2022-07-19 10:01:42
回答 1查看 685关注 0票数 1

我正在构建一个简单的应用程序,它有一个带有两个选项卡的TabLayout。一个选项卡是一个项目列表,您可以单击该列表并记录该项目。另一个选项卡是您在第一个选项卡中所做的注释列表。

我已经使用TabRows和HorizontalPager创建了一个TabRows和HorizontalPager,这是该部分的代码:

代码语言:javascript
运行
复制
 @OptIn(ExperimentalPagerApi::class)
@Composable
fun HorizontalPagerTabLayout(
    modifier: Modifier
) {
    val tabData = listOf("Records" to Icons.Default.Phone, "Notes" to Icons.Default.Star)
    val pagerState = rememberPagerState(
        initialPage = 0
    )
    val tabIndex = pagerState.currentPage
    val coroutineScope = rememberCoroutineScope()

    Column {
        TabRow(
            selectedTabIndex = tabIndex,
            modifier = modifier
        ) {
            tabData.forEachIndexed { index, _ ->
                Tab(
                    icon = {
                        Icon(imageVector = tabData[index].second, contentDescription = null)
                    },
                    selected = tabIndex == index,
                    onClick = {
                        coroutineScope.launch {
                            pagerState.animateScrollToPage(index)
                        }
                    },
                    text = {
                        Text(
                            tabData[index].first,
                            color = if (pagerState.currentPage == index) Color.White else Color.LightGray
                        )
                    })
            }
        }
        HorizontalPager(state = pagerState, count = tabData.size) { page ->
            Column(
                modifier = Modifier.fillMaxSize(),
                verticalArrangement = Arrangement.Center,
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
                when (page) {
                    0 -> RecordsScreen(modifier = Modifier)
                    1 -> NotesScreen(modifier = Modifier)
                }
            }
        }
    }
} 

RecordScreen中,我有一个逻辑,它将对记录做一个注释,并将其存储在RoomDB中。这就像预期的那样。

NotesScreen 中,我有一个viewModel,它将从RoomDB中提取所有注释,并在NotesScreen选项卡中播放它们。

下面是NotesScreen的代码:

代码语言:javascript
运行
复制
@Composable
fun NotesScreen(
    lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
    modifier: Modifier,
    notesViewModel: NotesViewModel = hiltViewModel()
) {

    val notesList by notesViewModel.notesStateData.collectAsState()

    // FAILED SOLUTION NUMBER 2
//    LaunchedEffect(Unit){
//        notesViewModel.getAllNotes()
//    }

    // FAILED SOLUTION NUMBER 3
//    DisposableEffect(lifecycleOwner) {
//        val observer = LifecycleEventObserver { _, event ->
//            when (event) {
//                Lifecycle.Event.ON_RESUME -> {
//                    notesViewModel.getAllNotes()
//                }
//                else -> {}
//            }
//        }
//        lifecycleOwner.lifecycle.addObserver(observer)
//        onDispose {
//            lifecycleOwner.lifecycle.removeObserver(observer)
//        }
//    }

    LazyColumn(
        contentPadding = (PaddingValues(horizontal = 16.dp, vertical = 8.dp)),
        modifier = modifier
    ) {
        items(items = notesList.orEmpty()) { note ->
            NoteItem(note)
        }
    }
}

从代码中可以看到,我注释掉了一些失败的解决方案。我的第一个解决方案是在notesViewModel.getAllNotes()init{}块中包含viewModel。但是这只调用了函数一次,而不是每次我回到NotesScreen时。

我的第二个解决方案是创建一个LaunchedEffect(Unit),因为我希望每次显示viewModel函数时都调用这个NotesScreen函数。但是它没有工作,它也只调用了一次getAllNotes()。

我的第三个解决方案是创建一个带有观察者的DisposableEffect,每当ON_RESUME发生时,它都会告诉我,但这也不起作用。

我使用调试器并记录了一些行为:

  • 当我使用init块时,init块在我打开应用程序时就会发生,而不是在我打开屏幕时发生。似乎immediately.

的HorizontalPager会加载屏幕。

  • 当我使用第二个解决方案时,LaunchEffect块会在我导航到屏幕时发生,但是即使我多次切换制表符,也不会再次调用它。

当我使用

  • 时,当我打开应用程序时,所有的生命周期状态都会在我打开应用程序时立即发生,ON_START、ON_CREATE和ON_RESUME在打开应用程序时就会被记录下来,尽管我还没有在NotesScreen上。这意味着viewModel函数只被调用一次,现在我无法看到我创建的新Notes,直到我重新启动应用程序.

我想要的行为:每次我打开NotesScreen时,我都想加载来自RoomDB的所有注释,而不仅仅是在应用程序启动时加载一次。我正在尝试触发VM函数,它不需要刷新布局或按钮就能自动从DB获得注释,但我似乎找不到解决方案。

任何帮助都将不胜感激。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-20 07:34:22

您可以使用snapshotFlow添加页面更改回调到寻呼机。它从可观察到的快照状态创建一个流。下面是一个示例代码

代码语言:javascript
运行
复制
    // Page change callback
    LaunchedEffect(pagerState) {
        snapshotFlow { pagerState.currentPage }.collect { page ->
            when (page) {
                0 -> viewModel.getAllNotes() // First page
                1 -> // Second page
                else -> // Other pages
            }
        }
    }
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73034912

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档