Compose имеет большие преимущества, но я чувствую, что читаемость и сложность кода увеличиваются с увеличением полей. Вот пример: [code]data class UserForm( val firstName: String, val lastName: String, val age: Int?, val gender: String, val phone: String, val email: String, val address: String, val city: String, val state: String, val zip: String, val country: String, val occupation: String, val company: String, val maritalStatus: String, val notes: String, )
sealed interface FormIntent { data class FirstNameChanged(val value: String) : FormIntent data class LastNameChanged(val value: String) : FormIntent data class AgeChanged(val value: String) : FormIntent data class GenderChanged(val value: String) : FormIntent data class PhoneChanged(val value: String) : FormIntent data class EmailChanged(val value: String) : FormIntent data class AddressChanged(val value: String) : FormIntent data class CityChanged(val value: String) : FormIntent data class StateChanged(val value: String) : FormIntent data class ZipChanged(val value: String) : FormIntent data class CountryChanged(val value: String) : FormIntent data class OccupationChanged(val value: String) : FormIntent data class CompanyChanged(val value: String) : FormIntent data class MaritalStatusChanged(val value: String) : FormIntent data class NotesChanged(val value: String) : FormIntent
data object Submit : FormIntent }
data class FormState( val firstName: String = "", val lastName: String = "", val age: String = "", val gender: String = "", val phone: String = "", val email: String = "", val address: String = "", val city: String = "", val state: String = "", val zip: String = "", val country: String = "", val occupation: String = "", val company: String = "", val maritalStatus: String = "", val notes: String = "",
val isSubmitting: Boolean = false, val successMessage: String? = null, val errorMessage: String? = null, val fieldErrors: Map = emptyMap() )
class FormViewModel( private val repository: UserFormRepository ) : ViewModel() {
private val _state = MutableStateFlow(FormState()) val state = _state.asStateFlow()
fun onIntent(intent: FormIntent) { when (intent) { is FormIntent.FirstNameChanged -> update { copy(firstName = intent.value) } is FormIntent.LastNameChanged -> update { copy(lastName = intent.value) } is FormIntent.AgeChanged -> update { copy(age = intent.value) } is FormIntent.GenderChanged -> update { copy(gender = intent.value) } is FormIntent.PhoneChanged -> update { copy(phone = intent.value) } is FormIntent.EmailChanged -> update { copy(email = intent.value) } is FormIntent.AddressChanged -> update { copy(address = intent.value) } is FormIntent.CityChanged -> update { copy(city = intent.value) } is FormIntent.StateChanged -> update { copy(state = intent.value) } is FormIntent.ZipChanged -> update { copy(zip = intent.value) } is FormIntent.CountryChanged -> update { copy(country = intent.value) } is FormIntent.OccupationChanged -> update { copy(occupation = intent.value) } is FormIntent.CompanyChanged -> update { copy(company = intent.value) } is FormIntent.MaritalStatusChanged -> update { copy(maritalStatus = intent.value) } is FormIntent.NotesChanged -> update { copy(notes = intent.value) } FormIntent.Submit -> submit() } }
private fun submit() { val current = _state.value val errors = validate(current) if (errors.isNotEmpty()) { update { copy(fieldErrors = errors) } return }
viewModelScope.launch { update { copy(isSubmitting = true, errorMessage = null, successMessage = null) } val form = UserForm( firstName = current.firstName, lastName = current.lastName, age = current.age.toIntOrNull(), gender = current.gender, phone = current.phone, email = current.email, address = current.address, city = current.city, state = current.state, zip = current.zip, country = current.country, occupation = current.occupation, company = current.company, maritalStatus = current.maritalStatus, notes = current.notes )
// Sample validation code - real project will be much more bigger than this private fun validate(s: FormState): Map { val errors = mutableMapOf() if (s.firstName.isBlank()) errors["firstName"] = "Required" if (s.lastName.isBlank()) errors["lastName"] = "Required" if (s.email.isBlank() || !android.util.Patterns.EMAIL_ADDRESS.matcher(s.email).matches()) errors["email"] = "Invalid email" if (s.age.toIntOrNull() == null) errors["age"] = "Enter valid age" return errors } }
@Composable fun FormScreen(viewModel: FormViewModel = /* DI or hiltViewModel() */) { val state by viewModel.state.collectAsState()
@Composable fun ErrorText(message: String?) { if (message != null) { Text( text = message, color = Color.Red, fontSize = 12.sp, modifier = Modifier.padding(start = 4.dp, bottom = 8.dp) ) } } [/code] Реализация становится раздутой. Как можно сократить стандартный код для проекта среднего размера?