Как обновить запись в базе данных комнаты через пользовательский интерфейс?

У меня есть приложение, которое позволяет пользователю добавлять коз с их данными, такими как имя, порода, возраст и пол, а также дополнительную информацию. Я только что создал функцию в GoatDao для обновления параметра goatInfo, и она работает внутри функции проверки базы данных.

 @Query("UPDATE goat SET goatInfo=:newInfo WHERE id=:id")
    fun updateInfoByQuery(id: Int, newInfo: String)

А это моя сущность Коза ˇ

@Entity
data class Goat(
    val goatName: String,
    val goatAge: String,
    val goatBreed: String,
    val goatInfo: String,
    val goatGender: String,
    @PrimaryKey(autoGenerate = true)
    val id: Int = 0
)

Я застрял в том, как реализовать функцию updateInfoByQuery в пользовательском интерфейсе. Я хочу иметь диалоговое окно, которое запускается при нажатии на козу и позволяет мне его обновлять.

Как реализовать эту функцию в пользовательском интерфейсе?

@Composable
fun UpdateDialog(state: GoatState, onDismiss: () -> Unit) {

    val patrick = FontFamily(
        Font(R.font.patrick_hand_sc, FontWeight.Black, FontStyle.Normal)
    )


    Dialog(
        onDismissRequest = { onDismiss() },
        properties = DialogProperties(usePlatformDefaultWidth = false)
    ) {
        

 }
}

Это мой основной код экрана козла:

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun GoatScreen( state: GoatState, onEvent: (GoatEvent) -> Unit) {
    val patrick = FontFamily(
        Font(R.font.patrick_hand_sc, FontWeight.Black, FontStyle.Normal)
    )



 


    Scaffold(
        containerColor = colorResource(R.color.brunswick_green),
        topBar = {
            CenterAlignedTopAppBar(
                modifier = Modifier
                    //.padding(6.dp)
                    .shadow(
                        elevation = 5.dp,
                        spotColor = Color.DarkGray,
                        shape = RoundedCornerShape(10.dp)
                    ),
                colors = topAppBarColors(
                    containerColor = colorResource(R.color.brunswick_green),
                            titleContentColor = MaterialTheme . colorScheme . primary,
                ),
                title = {

                    Text(
                        "Goats",
                        fontFamily = patrick,
                        color = colorResource(R.color.timberwolf),
                        textAlign = TextAlign.Center,
                        fontSize = 50.sp
                    )


                },

                )
        },
        floatingActionButton = {
            FloatingActionButton(onClick = { onEvent(GoatEvent.ShowDialog) }) {
                Icon(Icons.Default.Add, contentDescription = "Add")
            }
        },

    ) {
        padding ->
        if (state.isAddingGoat) {
            AddGoatDialog(state = state, onEvent = onEvent, modifier = Modifier )
        }



        LazyColumn(contentPadding = padding,
            modifier = Modifier.fillMaxSize(),
            verticalArrangement = Arrangement.spacedBy(16.dp) ) {
            item {
                Row(modifier = Modifier
                    .padding(8.dp)
                    .shadow(
                        elevation = 5.dp,
                        spotColor = Color.DarkGray,
                        shape = RoundedCornerShape(10.dp)
                    )
                    .background(color = colorResource(R.color.brunswick_green))
                    .horizontalScroll(rememberScrollState()),
                    verticalAlignment = Alignment.CenterVertically
                    ) {
                    SortType.entries.forEach { sortType ->
                        Row(modifier = Modifier.clickable { onEvent(GoatEvent.SortGoats(sortType)) }) {
                            RadioButton(selected = state.sortType == sortType, onClick = { onEvent(GoatEvent.SortGoats(sortType)) }, colors = RadioButtonDefaults.colors(Color.LightGray))
                            Text(text = sortType.name, color = colorResource(R.color.timberwolf))
                        }
                        
                    }

                }

                }


            items(state.goats) {goat ->
                Row(modifier = Modifier
                    .padding(12.dp)
                    .clickable {

                    }
                    .fillMaxWidth()
                    .background(color = Color.LightGray, shape = RoundedCornerShape(16.dp))
                    .padding(40.dp)) {



                    Column {
                        Text(text = "${goat.goatName} ${goat.goatAge}", fontFamily = patrick, fontSize = 20.sp
                        )
                    
                        Text(text = "${goat.goatBreed} ${goat.goatInfo}", fontFamily = patrick, fontSize = 20.sp)
                    }


                    
                    IconButton(onClick = { 
                        onEvent(GoatEvent.DeleteGoat(goat)) }) {
                        Icon(imageVector = Icons.Default.Delete, contentDescription = "Delete Goat")
                    }
                }
            }


        }

    }
}

Обновлено: Моя модель представления

package com.example.goatdatabase

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

class GoatViewModel(private val dao: GoatDao): ViewModel() {
    private val _state = MutableStateFlow(GoatState())
    private val _sortType = MutableStateFlow(SortType.NAME)
    @OptIn(ExperimentalCoroutinesApi::class)
    private val _goats = _sortType
        .flatMapLatest { sortType ->
            when(sortType) {
                SortType.NAME -> dao.getGoatsOrderedByName()
                SortType.BREED -> dao.getGoatsOrderedByBreed()
                SortType.AGE -> dao.getGoatsOrderedByAge()
                SortType.GENDER -> dao.getGoatsOrderedByGender()
            }
        }
        .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), emptyList())
    val state = combine(_state, _sortType, _goats) { state, sortType, goats ->
                state.copy(goats = goats, sortType = sortType) }
        .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), GoatState())



    fun onEvent(event: GoatEvent) {
        when(event) {
            is GoatEvent.DeleteGoat -> {
                viewModelScope.launch { dao.deleteGoat(event.goat) }
            }
            GoatEvent.HideDialog -> {
                _state.update { it.copy(isAddingGoat = false) }
            }
            GoatEvent.SaveGoat -> {
                val goatName = state.value.goatName
                val goatAge = state.value.goatAge
                val goatBreed = state.value.goatBreed
                val goatInfo = state.value.goatInfo
                val goatGender = state.value.goatGender

                if (goatName.isBlank() || goatAge.isBlank() || goatBreed.isBlank() || goatInfo.isBlank()) {
                    return
                }

                val goat = Goat(goatName = goatName, goatAge = goatAge, goatBreed = goatBreed, goatInfo = goatInfo, goatGender = goatGender)
                viewModelScope.launch { dao.insertGoat(goat) }
                _state.update{it.copy(isAddingGoat = false,
                    goatName = "",
                    goatInfo = "",
                    goatBreed = "",
                    goatAge = ""
                    )}

            }
            is GoatEvent.SetGoatAge -> {
                _state.update {it.copy(goatAge = event.goatAge)}
            }
            is GoatEvent.SetGoatBreed -> {
                _state.update{it.copy(goatBreed = event.goatBreed)}
            }
            is GoatEvent.SetGoatInfo -> {
                _state.update { it.copy(goatInfo = event.goatInfo) }
            }
            is GoatEvent.SetGoatName -> {
                _state.update { it.copy(goatName = event.goatName) }
            }
            GoatEvent.ShowDialog -> {
                _state.update{it.copy(isAddingGoat = true)}
            }

            is GoatEvent.SortGoats -> {
                _sortType.value = event.sortType
            }

            is GoatEvent.SetGoatGender -> {
                _state.update {it.copy(goatGender = event.goatGender)}
            }

           
        }
    }
}

РЕДАКТИРОВАТЬ ::::

Я обновил модель представления, чтобы запускать диалоговое окно для каждого козла, но когда я ввожу данные и нажимаю "Сохранить", ничего не меняется??

@Composable
fun UpdateDialog(onEvent: (GoatEvent) -> Unit, state: GoatState, onDismiss: () -> Unit) {

val patrick = FontFamily(
    Font(R.font.patrick_hand_sc, FontWeight.Black, FontStyle.Normal)
)
 //   val goat = Goat(state.goatName, state.goatAge, state.goatBreed, state.goatGender, state.goatInfo)


   Dialog(
      onDismissRequest = { onEvent(GoatEvent.HideNewDialog) },
        properties = DialogProperties(usePlatformDefaultWidth = false)

    ) {
        Column {


       TextField( value = state.goatInfo, onValueChange = {onEvent(GoatEvent.SetGoatInfo(it))},
           placeholder = { Text(text = "Goat Info") })

       Button(onClick = { onEvent(GoatEvent.SaveGoat) }) {
           Text(text = "Save")

       }

        }
 }
}

Вот это в модели представления:

 GoatEvent.ShowNewDialog -> {
                _state.update{it.copy(isUpdatingGoat = true)}
            }

is GoatEvent.UpdateGoatInfo -> {
                dao.updateInfoByQuery(id = state.value.goatId, newInfo = state.value.goatInfo)
            }

Откуда новая информация? Я не вижу TextField или чего-то еще... Кроме того, нам нужно будет увидеть соответствующие части вашей модели представления.

Leviathan 26.03.2024 11:27

Я отредактировал вопрос, чтобы показать модель представления. Что касается текстовых полей, я не реализовал их в диалоговом окне, потому что не был уверен, как мне это сделать, чтобы ссылаться на функцию для обновления.

xxxVxxxlinux 26.03.2024 11:44

Хорошо. Итак, какое из событий следует использовать для обновления информации? Я не вижу события UpdateGoat. Кроме того, есть ли конкретная причина, по которой вы не просто заменяете весь объект козла в базе данных, когда он был изменен? Да, это потребует небольших накладных расходов, но это будет намного проще, чем использовать весь шаблонный код для обновления каждого поля базы данных отдельно.

Leviathan 26.03.2024 12:26

это GoatEvent.UpdateGoatInfo -> { TODO() }

xxxVxxxlinux 26.03.2024 12:51

Я не знаю, как использовать функцию обновления. Я новичок в этом, и документация не помогла мне. Как мне заменить весь объект?

xxxVxxxlinux 26.03.2024 12:53

Хорошо, так почему бы вам просто не заменить TODO() на dao.updateInfoByQuery(...)? Замена записи работает так же, как и вставка, вам просто нужно указать стратегию конфликта: @Insert(onConflict = OnConflictStrategy.REPLACE) fun save(goat: Goat): Long

Leviathan 26.03.2024 17:46

Пожалуйста, проверьте мое новое редактирование в посте!

xxxVxxxlinux 27.03.2024 10:21
2
7
119
0
Перейти к ответу Данный вопрос помечен как решенный

Другие вопросы по теме