如何从 Jetpack Compose 屏幕将附加数据传递到 ViewModel?

问题描述 投票:0回答:1

我正在导航到最初在屏幕上显示

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
方法中,我可以看到按下的按钮,但我也不知道如何获取日期。

android kotlin android-jetpack-compose
1个回答
0
投票

通过执行

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")
    }
}
                
© www.soinside.com 2019 - 2024. All rights reserved.