我正在导航到最初在屏幕上显示
DatePickerModal
和一组按钮的目的地。当用户选择一个日期并单击其中一个按钮时,我想将所选日期和按下的按钮传递到 ViewModel,以便基于该数据,可以在数据存储库中执行操作。
我的问题是我不知道如何同时传递两个数据。
这些是我的代码的相关部分:
CalendarScreen
@ExperimentalLayoutApi
@ExperimentalCoroutinesApi
@Composable
internal fun CalendarScreen(
viewModel: CalendarViewModel = hiltViewModel()
) {
val selectedTopicId by viewModel.selectedTopicIdd.collectAsStateWithLifecycle()
var showModal by remember { mutableStateOf(true) }
ButtonsScreenCalendar(
onTopicButtonClicked = viewModel::onTopicClick,
onDateSelected = viewModel::onDateSelected
)
var selectedDate by remember { mutableStateOf<Long?>(null) }
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 (showModal) {
DatePickerModal(
onDateSelected = {
selectedDate = it
viewModel::onDateSelected
showModal = false
},
onDismiss = { showModal = false }
)
}
}
ButtonsScreenCalendar
@ExperimentalLayoutApi
@Composable
fun ButtonsScreenCalendar(
onTopicButtonClicked: (String) -> Unit,
onDateSelected: (Long)-> Unit
) {
/* Some code */
FlowRow(modifier = rowModifier) {
it.items.forEach {
HomeButton(it) {
onTopicButtonClicked(it.id.toString())
onDateSelected
}
Spacer(modifier = chipModifier)
}
}
}
HomeButton
@Composable
fun HomeButton(
itemUI: ItemUI,
onClick: () -> Unit
) {
AssistChip(
onClick = { onClick() },
label = { Text(itemUI.title) }
)
}
CalendarViewModel
@HiltViewModel
class CalendarViewModel @Inject constructor(
private val savedStateHandle: SavedStateHandle,
val universalisRepository: UniversalisRepository,
getTopicWithDate: GetTopicWithDateUseCase,
) : ViewModel() {
private val selectedTopicIdKey = "selectedTopicIdKey"
private val selectedTopicId = savedStateHandle.getStateFlow(
key = selectedTopicIdKey,
initialValue = 1, //TODO
)
//TODO Invoque use case passing topic and date
/* Some code */
fun onTopicClick(topicId: String?) {
savedStateHandle[TOPIC_ID_ARG] = topicId
}
}
在
onTopicClick
的CalendarViewModel
方法中,我可以看到按下的按钮,但我也不知道如何获取日期。
通过执行
viewModel::onDateSelected
,您将获得可调用方法引用。然而,问题是您没有对该可调用方法引用执行任何操作。你的 IDE 实际上应该抱怨这一点:
该表达式未使用
因此,要执行您要获取引用的函数,您需要首先将获取的引用存储在某处,然后显式调用它:
val myViewModelFunctionReference = viewModel::onDateSelected
myViewModelFunctionReference.invoke(it)
然而,这与简单的调用完全相同
viewModel.onDateSelected(it)
但是什么情况下可以使用函数引用呢?
当您需要提供 function 作为 parameter 时,可以使用函数引用。请看下面的例子:
@Composable
fun DemoComposable() {
val viewModel = MyViewModel()
Button(
onClick = {
val myViewModelFunction = viewModel::printLog
printLog.invoke()
}
) {
Text(text = "LOG")
}
}
class MyViewModel {
fun printLog() {
Log.d("TEST", "SUCCESSFUL")
}
}
正如我们之前提到的,我们可以将其简化为
@Composable
fun DemoComposable() {
val viewModel = MyViewModel()
Button(
onClick = {
viewModel.printLog()
}
) {
Text(text = "LOG")
}
}
现在,我们看到实际上,除了直接调用
onClick
lamdba 中的另一个函数之外,我们什么也没做。由于 onClick
和 printLog
函数具有相同的 () -> Unit
函数签名,因此我们可以直接将函数引用作为 onClick
参数传递,并摆脱不必要的 lamdba:
@Composable
fun DemoComposable() {
val viewModel = MyViewModel()
Button(
onClick = viewModel::printLog
) {
Text(text = "LOG")
}
}