Arpan Sarkar
08/01/2021, 6:06 PMLiveData
to how can i convert the MediatorLiveData
part to StateFlow
import androidx.lifecycle.LiveData
import androidx.lifecycle.MediatorLiveData
import androidx.lifecycle.MutableLiveData
abstract class InputFrom {
private val _isFromValid = MediatorLiveData<Boolean>()
val isFromValid: LiveData<Boolean>
get() = _isFromValid
abstract val fields: List<LiveInputField<*>>
fun init() {
fields.forEach { inputField ->
_isFromValid.addSource(inputField.value) { changedValue ->
inputField.validate(changedValue)
_isFromValid.value = fields.all {
it.isValid
}
}
}
}
inner class LiveInputField<T>(
private val errorMessage: String? = null,
private val predicate: (T?) -> Boolean
) {
val value = MutableLiveData<T>()
private val _error = MutableLiveData<String>()
val errorText: LiveData<String>
get() = _error
var isValid: Boolean = false
fun validate(value: Any?) {
@Suppress("UNCHECKED_CAST")
return if (predicate(value as? T)) {
_error.value = null
isValid = true
} else {
_error.value = errorMessage
isValid = false
}
}
}
}
Example Usages:
class LoginFrom : InputFrom() {
val username =
LiveInputField<String>("At least 4 characters, only letters, numbers, ., _ allowed.") {
!it.isNullOrBlank() &&
Pattern.compile("[a-zA-Z0-9_.]{4,}")
.matcher(it)
.matches()
}
val password =
LiveInputField<String>(
"8 characters or more, at least one number, one uppercase, one lowercase."
) {
!it.isNullOrBlank()/* &&
Pattern.compile("((?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,})")
.matcher(it)
.matches()*/
}
override val fields: List<LiveInputField<*>>
get() = listOf(
username,
password
)
}
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.StateFlow
abstract class InputForm {
private val _isValid = MutableStateFlow(false)
val isValid: SharedFlow<Boolean>
get() = _isValid
abstract val fields: List<Field<*>>
fun init() {
// TODO: implement validation when Field#value changes
}
inner class Field<T>(
initialValue: T? = null,
private val errorMessage: String? = null,
private val validator: (T?) -> Boolean
) {
val value = MutableStateFlow(initialValue)
private val _error = MutableStateFlow<String?>(null)
val errorText: StateFlow<String?>
get() = _error
var isValid: Boolean = false
fun validate(value: Any?) {
@Suppress("UNCHECKED_CAST")
return if (validator(value as? T)) {
_error.value = null
isValid = true
} else {
_error.value = errorMessage
isValid = false
}
}
}
}