首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Android Paging3 -从带有复合的ViewModel中刷新

Android Paging3 -从带有复合的ViewModel中刷新
EN

Stack Overflow用户
提问于 2022-08-09 14:53:33
回答 1查看 319关注 0票数 0

我正在使用带有寻呼3喷气式组合库,并且刚刚实现了对某些分页数据(使用材料库的SwipeToDismiss可组合)的清除。

一旦完成了滑动操作,我将调用ViewModel中的一个方法向服务器发送更新(将消息标记为read或删除消息)。完成此操作后,显然需要刷新分页数据。

我的当前方法是从我的ViewModel函数中调用一个函数,该函数将处理LazyPagingItems上的刷新,但这感觉是错误的。

有没有更好的方法?

我的ViewModel基本上是这样的:

代码语言:javascript
运行
复制
@HiltViewModel
class MessageListViewModel @Inject constructor(
    private val repository: Repository
): ViewModel() {
    companion object {
        private const val TAG = "MessageListViewModel"
    }

    val messages : Flow<PagingData<Message>> = Pager(
        PagingConfig(
            enablePlaceholders = false,
        )
    ) {
        MessagePagingSource(repository)
    }.flow.cachedIn(viewModelScope)

    fun markRead(guid: String, onComplete: () -> Unit) {
        viewModelScope.launch(Dispatchers.IO) {
            try {
                repository.markMessageRead(guid)

                onComplete()
            } catch (e: Throwable) {
                Log.e(TAG, "Error marking message read: $guid", e)
            }
        }
    }
}

在我的可组合消息列表中,它看起来有点像以下内容:

代码语言:javascript
运行
复制
@Composable
fun MessageListScreen(
    vm: MessageListViewModel = viewModel(),
) {
    val messages: LazyPagingItems<MessageSummary> = vm.messages.collectAsLazyPagingItems()
    val refreshState = rememberSwipeRefreshState(
        isRefreshing = messages.loadState.refresh is LoadState.Loading,
    )

    Scaffold(
        topBar = {
            SmallTopAppBar (
                title = {
                    Text(stringResource(R.string.message_list_title))
                },
            )
        }
    ) { paddingValues ->
        Box(
            modifier = Modifier
                .fillMaxSize()
                .padding(paddingValues),
        ) {
            SwipeRefresh(
                state = refreshState,
                onRefresh = {
                    messages.refresh()
                },
            ) {
                LazyColumn(
                    modifier = Modifier.fillMaxSize(),
                    horizontalAlignment = Alignment.CenterHorizontally,
                    verticalArrangement = Arrangement.Top,
                ) {
                    items(
                        items = messages,
                        key = { it.guid }
                    ) { message ->
                        message?.let {
                            MessageRow(
                                onMarkRead = {
                                    vm.markRead(message.guid) {
                                        messages.refresh()
                                    }
                                },
                            )
                        }
                    }
                }
            }
        }
    }
}

就像我说的,这确实有效,只是感觉不太像最干净的方法。

我对处理流程很陌生,所以我不知道我还有没有其他的窍门.

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-10-06 15:15:19

最后我实现了这样的东西:

视图模型:

代码语言:javascript
运行
复制
class MessageListViewModel @Inject constructor(
    private val repository: Repository,
): ViewModel() {
    sealed class UiAction {
        class MarkReadError(val error: Throwable): UiAction()
        class MarkedRead(val id: Long): UiAction()
    }

    private val _uiActions = MutableSharedFlow<UiAction>()

    val uiActions = _uiActions.asSharedFlow()
        .shareIn(
            scope = viewModelScope,
            started = SharingStarted.WhileSubscribed(),
        )


    fun markRead(id: Long) {
        viewModelScope.launch(Dispatchers.IO) {
            try {
                repository.markMessageRead(id)

                _uiActions.emit(UiAction.MarkedRead(id))
            } catch (e: Throwable) {
                Log.e(TAG, "Error marking message read: $id", e)

                _uiActions.emit(UiAction.MarkReadError(e))
            }
        }
    }
}

视图

代码语言:javascript
运行
复制
@Composable
fun MessageListScreen(
    vm: MessageListViewModel = viewModel(),
    onMarkReadFailed: (String) -> Unit,
) {
    val context = LocalContext.current
    val lifecycleOwner = LocalLifecycleOwner.current

    val messages: LazyPagingItems<Message> = vm.messages.collectAsLazyPagingItems()
    val refreshState = rememberSwipeRefreshState(
        isRefreshing = messages.loadState.refresh is LoadState.Loading,
    )

    LaunchedEffect(lifecycleOwner) {
        lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
            vm.uiActions.collectLatest {
                when (it) {
                    is MessageListViewModel.UiAction.MarkReadError -> {
                        val msg = it.error.localizedMessage ?: it.error.message

                        val message = if (!msg.isNullOrEmpty()) {
                            context.getString(R.string.error_unknown_error_with_message, msg)
                        } else {
                            context.getString(R.string.error_unknown_error_without_message)
                        }

                        onMarkReadFailed(message)
                    }
                    is MessageListViewModel.UiAction.MarkedRead -> {
                        messages.refresh()
                    }
                }
            }
        }
    }

    SwipeRefresh(
        state = refreshState,
        onRefresh = {
            messages.refresh()
        },
    ) {
        LazyColumn(
            modifier = Modifier.fillMaxSize(),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Top,
            state = listState,
        ) {
            items(
                items = messages,
                key = { it.id }
            ) { message ->
                message?.let {
                    MessageRow(
                        onMarkRead = {
                            vm.markRead(message.id)
                        },
                    )
                }

                FadedDivider()
            }

            messages.apply {
                when (loadState.append) {
                    is LoadState.Loading -> {
                        item {
                            LoadingRow(R.string.messages_loading)
                        }
                    }
                    else -> {}
                }
            }
        }
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73293915

复制
相关文章

相似问题

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