Estou um pouco confuso com o seguinte cenário:
Inicialmente, estou exibindo um modal DatePicker na tela.
Quando o usuário seleciona uma data, eu exibo vários botões.
E quando o usuário clicar em qualquer um desses botões, quero passar para o ViewModel os dois dados: a data selecionada e o tipo de botão que foi pressionado , para buscar dados no repositório com esses dois critérios.
Meu problema é que não consigo encontrar uma maneira de passar os dois dados antes que o ViewModel seja incluído.
Estou tentando fazer algo parecido InterestsScreen
com o Now In Android .
Tenho um código semelhante em outro cenário onde funciona, mas lá a data é retirada do sistema, então não há problema. Aqui a data deve ser dada pelo usuário, de um DatePicker.
Não mostro o código para o UseCase ou o Repository, esse código funciona bem quando passo os parâmetros corretos. Meu problema é que não sei como fazer a chamada para o ViewModel quando tenho a data selecionada e o tipo de botão que o usuário pressionou.
Mostro as partes relevantes do meu código:
NavGraphBuilder
composable<CalendarRoute> {
CalendarScreen(onTopicClick = onTopicClick,onDateSelected={})
CalendarScreen
(chamado de 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
}
}
Você combinou incorretamente dois estágios diferentes de fluxo.
O
topicId
edate
são parâmetros de consulta para o Tópico, então a consulta só começa quando eles mudam.Então os resultados da sua consulta de tópico serão como:
Então o seu
uiState
será: