我对以下场景有点困惑:
最初我在屏幕上显示 DatePicker 模式。
当用户选择日期时,我会显示几个按钮。
当用户单击任何这些按钮时,我想将两条数据传递给 ViewModel:所选日期和按下的按钮类型,以使用这两个数据在存储库中搜索数据标准。
我的问题是,在包含 ViewModel 之前,我找不到传递这两条数据的方法。
我正在尝试在 Now In Android 中做类似
InterestsScreen
的事情。
我在另一个场景中有一个类似的代码,它可以工作,但是日期是从系统中获取的,所以没有问题。这里的日期必须由用户从 DatePicker 给出。
我没有显示用例或存储库的代码,当我向其传递正确的参数时,该代码可以正常工作。我的问题是,当我有选定的日期和用户按下的按钮类型时,我不知道如何调用 ViewModel。
我展示了我的代码的相关部分:
NavGraphBuilder
composable<CalendarRoute> {
CalendarScreen(onTopicClick = onTopicClick,onDateSelected={})
CalendarScreen
(从 NavGraphBuilder 调用)@Composable
fun CalendarScreen(
onTopicClick: (String) -> Unit,
onDateSelected: (Long?) -> Unit,
viewModel: CalendarViewModel = hiltViewModel()
) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
DatePickerAndButtons(
onTopicClick = viewModel::onTopicClick,
onDateSelected = viewModel::onDateSelected,
uiState = uiState
)
}
DatePickerAndButtons
@ExperimentalLayoutApi
@Composable
fun DatePickerAndButtons(
onTopicClick: (String) -> Unit,
onDateSelected: (Long?) -> Unit,
uiState: CalendarUiState
) {
var showTopics by remember { mutableStateOf(false) }
var showDatePicker by remember { mutableStateOf(true) }
var selectedDate by remember { mutableStateOf<Long?>(null) }
when (uiState) {
CalendarUiState.Empty -> Text("Empty")
CalendarUiState.Error -> Text("Error")
CalendarUiState.Loading -> {
Text("Loading")
//showDatePicker=true
}
is CalendarUiState.CalendarData -> {
showTopics=false
//showDatePicker=false
if(uiState.topics.isNotEmpty()) {
//Show data
}else{
//¿?
}
}
}
if (selectedDate != null) {
val date = Date(selectedDate!!)
val formattedDate = SimpleDateFormat("MMM dd, yyyy", Locale.getDefault()).format(date)
Text("Selected date: $formattedDate")
} else {
Text("No date selected")
}
if (showDatePicker) {
DatePickerModal(
onDateSelected = {
selectedDate = it
onDateSelected(it)
//viewModel.onDateSelected(selectedDate)
showDatePicker = false
showTopics=true
},
onDismiss = { showDatePicker = false }
)
}
if(showTopics) {
//Code that create buttons to be clicked
}
}
ViewModel
@HiltViewModel
class CalendarViewModel @Inject constructor(
private val savedStateHandle: SavedStateHandle,
val userDataRepository: UserDataRepository,
val universalisRepository: UniversalisRepository,
getTopicWithDate: GetUniversalisFromCalendarUseCase,
) : ViewModel() {
private val selectedTopicIdKey = "selectedTopicIdKey"
private val selectedDateKey = "selectedDateKey"
private val calendarRoute: CalendarRoute = savedStateHandle.toRoute()
private val selectedTopicId = savedStateHandle.getStateFlow(
key = selectedTopicIdKey,
initialValue = "1" //calendarRoute.topicId,
)
private val selectedDate = savedStateHandle.getStateFlow(
key = selectedDateKey,
initialValue = 0
)
val uiState: StateFlow<CalendarUiState> = combine(
selectedTopicId,
getTopicWithDate.invoke(
date = selectedDate.value,
title = "TODO:Title",
selectedTopicId = selectedTopicId.value
),
CalendarUiState::CalendarData,
).
stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = CalendarUiState.Loading,
)
fun onTopicClick(topicId: String?) {
savedStateHandle[selectedTopicIdKey] = topicId
}
fun onDateSelected(date: Long?) {
savedStateHandle[selectedDateKey] = date
}
}
您错误地组合了两个不同的流程阶段。
topicId
和date
是Topic的查询参数,所以只有当它们改变时才会开始查询。 private val topics: Flow<YourTopicsModel> = combine(
selectedDate,
selectedTopicId,
){date,topicId->
date to topicId
}.flatMapLatest {
getTopicWithDate(
date = it.first,
title = "TODO:Title",
selectedTopicId = it.second
)
}
那么你的
uiState
将是:
val uiState: StateFlow<CalendarUiState> = combine(
selectedTopicId,
topics,
CalendarUiState::CalendarData,
).
stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = CalendarUiState.Loading,
)