0

I am developing an android app, and my use case requires validating some user's inputs.

As an example, I have depth value (in reality, it has more than 20 inputs) which should be something between 3 and 100 inclusive. and since it is an info provided by the user to do some calculation, I have a Dialog for that, my questions is: how to validate the input in real time using the view model (is it the correct way to validate the input?). My initial naive solution was to create a helper class that validate the TextInput value

fun validateDepth(depth: String): Boolean {
    return depth.isNotBlank() && depth.toIntOrNull() != null && depth.toInt() in 3..100
}

and then

DepthPicker(
    value = depthValue,
    onValueChange = onDepthValueChange,
    validator = DepthValidator::validateDepth // <---- HERE: I dind't like this part
)

But I didn't like the fact that the UI is doing the validation and not the ViewModel, this is making it hard to test. and the depth value must be validated before sending it to the repository.

my dialog is a simple composable

Dialog(onDismissRequest = onDismissRequest) { 
    ...
    TextField(...)
}

UiState

data class UiState(val depth: Int?)

ViewModel

@HiltViewModel
class DepthViewModel @Inject constructor(
    private val depthRepository: DepthRepository,
) : ViewModel() {
    private val _uiState = MutableStateFlow(DepthUiState())
    val uiState = _uiState.AsStateFlow()

    fun updateDepth(depth: Int?) = _uiState.update { it.copy(depth = depth) }
    ....
}

TL;DR: how/where to validate user's input on a dialog with a text field while typing? NOTE if the user already entered a valid value, and then decided to change it, click on edit, change it to a non valid and then click cancel, then the old valid value must be shown.

1 Answer 1

0

You can do it inside domain layer using a UseCase or Interactor class which only consists of non-Android classes, objects or functions that makes it easy to unit test or move to another ViewModel when required. UseCases are single responsiblity classes that handle business logic as stated in The Clean Architecture by Robert C. Martin (Uncle Bob)

Use Cases The software in this layer contains application specific business rules. It encapsulates and implements all of the use cases of the system. These use cases orchestrate the flow of data to and from the entities, and direct those entities to use their enterprise wide business rules to achieve the goals of the use case.

We do not expect changes in this layer to affect the entities. We also do not expect this layer to be affected by changes to externalities such as the database, the UI, or any of the common frameworks. This layer is isolated from such concerns.

And official Android document for Android what's domain layer and how you can use it with Jetpack Compose. You can check out JetNews app or ioshed app for more details either.

And how that circle block is translated to Android can be viewed as in this image.

https://developer.android.com/topic/architecture/domain-layer

enter image description here

Sign up to request clarification or add additional context in comments.

4 Comments

Architectural-wise it makes sense, but, if I create ValidateDepthUseCase, then I have to expose a function that takes the same parameters as the use case to compose to use?
You will only expose your function to ViewMode. Your Composable will only receive state/data from ViewModel while only passing event to ViewModel as in this document. developer.android.com/jetpack/compose/mental-model#paradigm
Interaction should with UI should be between only your presenter(ViewModel) layer. And viewModel should provide state while getting user events or inputs from ui then passing these inputs to UseCase which uses Repository to get data and then transform this data to one that can be used in ViewModel. Then you convert this model to uiState in ViewModel for Ui to be totally indepedent from your business logic, how you store data and other implementation details
But in my case, I don't want that the data get updated in the viewmodel if it is not valid because I have a dialog, so the OK should be disabled if the input is not valid, my question mainly is what would be the best place to have such validation.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.