Search code examples
androidandroid-jetpack-composeandroid-jetpack

Android Jetpack Compose - MVVM recompose on TextField


Trying to get a TextField to recompose using the MVVM pattern doesn't seem to work?

I get the input when I do Log.d but zero recomposition happening. Searched all over and cannot seem to find a "simple" solution to this.

It seems all the examples are doing everything inside the composable and not using MVVM?

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            TextFieldRecomposeTheme {
                Surface(color = MaterialTheme.colors.background) {
                    GetInput(myVM = MyViewModel())
                }
            }
        }
    }
}

@Composable
fun GetInput(myVM: MyViewModel) {

    Column(
        modifier = Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {

        OutlinedTextField(
            value = myVM.updatedClientData.firstName,
            onValueChange = { myVM.updatedClientData.firstName = it },
            label = { Text(text = "Firstname")}
        )
    }

}

class MyViewModel() : ViewModel() {

    var updatedClientData by mutableStateOf<Client>(Client())

    // This is just for testing - the data will be loaded from a remote server and set
    init {
        updatedClientData = Client(
            id = 1,
            firstName = "Test",
            lastName = "User",
            email = "[email protected]",
            mobilePhone = "777666555"
        )
    }
}

data class Client(
    @SerializedName("Id")
    val id: Int = 0,
    @SerializedName("FirstName")
    var firstName: String = "",
    @SerializedName("LastName")
    val lastName: String = "",
    @SerializedName("Email")
    val email: String = "",
    @SerializedName("MobilePhone")
    val mobilePhone: String = "",
)

Solution

  • The reason is that you are updating field inside a class. Field that isn't a mutable observable property. Only the change of whole updatedClientData will trigger recomposition. You can fix that using myVM.updatedClientData = myVM.updatedClientData.copy(firstName = it)