Я строю приложение Todo List. Когда пользователь нажимает на значок «Добавить», появляется диалог, позволяющий им добавить задачу в список. После нажатия «Подтвердить» в диалоговом окне событие CLICK должно вызвать обратный вызов, который делегирует обработку ошибок в ViewModel. Когда ViewModel определяет ошибку, она обновляет MutableStateFlow, который собирается в представлении. Как только представление обнаружит ошибку, он должен отобразить ошибку в диалоговом окне «Открыть». Я пытаюсь найти способ закрыть диалог после того, как «Подтверждение» нажимается, не предотвращая открытие диалога в первую очередь (нажав Add). До сих пор, когда проверка проходит и в настоящее время открыт диалог, я хочу закрыть диалог, поэтому я установил < /p>
if (!verificationFailed && isDialogOpen) isDialogOpen = false
< /code>
Но, поскольку проверка запускается как false, когда нажат значок добавления, что условия является истинной, которая предотвращает появление диалога в первую очередь.import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import com.example.todopractice.ui.theme.ToDoPracticeTheme
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.OutlinedTextField
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
class MainActivity : ComponentActivity() {
private val vm by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContent {
ToDoPracticeTheme {
var isDialogOpen by rememberSaveable { mutableStateOf(false) }
val tasks by vm.tasks.collectAsState()
val verificationFailed by vm.inputError.collectAsState()
Scaffold(
modifier = Modifier.fillMaxSize(),
topBar = {
AppBar(
{
isDialogOpen = true
vm.clearError()
Log.d("TRACE", "+ icon was clicked, isDialogOpen=$isDialogOpen")
}
)
}) { innerPadding ->
//}
LazyColumn {
Log.d("TRACE", "$tasks")
items(tasks) {
TaskRow(it)
}
}
if (!verificationFailed && isDialogOpen) isDialogOpen = false
if (isDialogOpen) InsertTaskDialog(
onNegativeClick = {
isDialogOpen = false
vm.clearError() // Uncomment if you add this function
},
onPositiveClick = {
vm.onSubmitTask(it)
},
verificationFailed
)
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AppBar(onOpenDialogClick: ()->Unit) {
TopAppBar(
title = { Text("ToDo") },
actions = {
IconButton(onClick = { onOpenDialogClick() }) {
Icon(imageVector = Icons.Default.Add, contentDescription = "Open Dialog")
}
}
)
}
@Composable
fun TaskRow(task: Task) {
Row {
Text(text = task.name)
}
}
@Composable
fun InsertTaskDialog(
onNegativeClick: ()->Unit,
onPositiveClick: (Task)->Unit,
verificationFailed: Boolean) {
var nameInput by rememberSaveable { mutableStateOf("") }
AlertDialog(
onDismissRequest = onNegativeClick,
confirmButton = {
Button(onClick = {
onPositiveClick(Task(nameInput,false))
}) {
Text(text = "Confirm")
} },
modifier = Modifier,
dismissButton = {
Button(onClick = { onNegativeClick() }) {
Text(text = "Cancel")
} },
title = { Text(text = "New Task") },
text = {
Column {
OutlinedTextField(
value = nameInput,
onValueChange = { nameInput = it },
label = { Text(text = "Name") }
)
if (verificationFailed) {
Spacer(modifier = Modifier.height(8.dp))
Text(text = "Name is required", color = Color.Red)
}
}
}
)
}
}
< /code>
mainviewmodel < /p>
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
data class Task(val name: String, val isComplete: Boolean)
class MainViewModel: ViewModel() {
private val _tasks = MutableStateFlow(listOf())
val tasks = _tasks.asStateFlow()
private val _inputError = MutableStateFlow(false)
val inputError = _inputError.asStateFlow()
fun onSubmitTask(task: Task) {
if (task.name.isEmpty()) {
_inputError.update { true }
} else {
_inputError.update { false }
_tasks.update {
it + task
}
}
}
fun clearError() {
_inputError.update { false }
}
}
Я знаю, что мог бы избежать этого, проверив ошибку внутри моего композиции, но я бы хотел, чтобы TP помещал эту логику в моем ViewModel, чтобы сделать ее проверкой.>
Я строю приложение Todo List. Когда пользователь нажимает на значок «Добавить», появляется диалог, позволяющий им добавить задачу в список. После нажатия «Подтвердить» в диалоговом окне событие CLICK должно вызвать обратный вызов, который делегирует обработку ошибок в ViewModel. Когда ViewModel определяет ошибку, она обновляет MutableStateFlow, который собирается в представлении. Как только представление обнаружит ошибку, он должен отобразить ошибку в диалоговом окне «Открыть». Я пытаюсь найти способ закрыть диалог после того, как «Подтверждение» нажимается, не предотвращая открытие диалога в первую очередь (нажав Add). До сих пор, когда проверка проходит и в настоящее время открыт диалог, я хочу закрыть диалог, поэтому я установил < /p> [code]if (!verificationFailed && isDialogOpen) isDialogOpen = false < /code> Но, поскольку проверка запускается как false, когда нажат значок добавления, что условия является истинной, которая предотвращает появление диалога в первую очередь.import android.os.Bundle import android.util.Log import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.activity.viewModels import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Add import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import com.example.todopractice.ui.theme.ToDoPracticeTheme import androidx.compose.foundation.lazy.items import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button import androidx.compose.material3.OutlinedTextField import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp
class MainActivity : ComponentActivity() { private val vm by viewModels()
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { ToDoPracticeTheme { var isDialogOpen by rememberSaveable { mutableStateOf(false) } val tasks by vm.tasks.collectAsState() val verificationFailed by vm.inputError.collectAsState()
data class Task(val name: String, val isComplete: Boolean)
class MainViewModel: ViewModel() { private val _tasks = MutableStateFlow(listOf()) val tasks = _tasks.asStateFlow()
private val _inputError = MutableStateFlow(false) val inputError = _inputError.asStateFlow()
fun onSubmitTask(task: Task) { if (task.name.isEmpty()) { _inputError.update { true } } else { _inputError.update { false } _tasks.update { it + task } } }
fun clearError() { _inputError.update { false } } } [/code] Я знаю, что мог бы избежать этого, проверив ошибку внутри моего композиции, но я бы хотел, чтобы TP помещал эту логику в моем ViewModel, чтобы сделать ее проверкой.>