我正在使用带有寻呼3的喷气式组合库,并且刚刚实现了对某些分页数据(使用材料库的SwipeToDismiss
可组合)的清除。
一旦完成了滑动操作,我将调用ViewModel中的一个方法向服务器发送更新(将消息标记为read或删除消息)。完成此操作后,显然需要刷新分页数据。
我的当前方法是从我的ViewModel函数中调用一个函数,该函数将处理LazyPagingItems
上的刷新,但这感觉是错误的。
有没有更好的方法?
我的ViewModel基本上是这样的:
@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)
}
}
}
}
在我的可组合消息列表中,它看起来有点像以下内容:
@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()
}
},
)
}
}
}
}
}
}
}
就像我说的,这确实有效,只是感觉不太像最干净的方法。
我对处理流程很陌生,所以我不知道我还有没有其他的窍门.
发布于 2022-10-06 15:15:19
最后我实现了这样的东西:
视图模型:
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))
}
}
}
}
视图
@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 -> {}
}
}
}
}
}
https://stackoverflow.com/questions/73293915
复制相似问题