-1

LoginScreen() is my composable function and i am trying to use a textfield inside it which takes email data from my viewmodel.Everytime my email values changes, LoginScreen function is recomposed and reinitialises my viewModel which results in no change in my textfield. I am wondering why is this happening and how to fix it.

@Composable
fun LoginScreen(navController: NavHostController
){

    var viewModel=LoginScreenViewModel(navController = navController, LocalContext.current)

    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(primary)
            .verticalScroll(rememberScrollState())
    ){
        TextField(value = viewModel.emailText
            , onValueChange = {
                viewModel.emailText=it
                Log.i("Email text",viewModel.emailText)
            },
            placeholder = {
                Text("Email")
            },
            keyboardOptions = KeyboardOptions(
                keyboardType = KeyboardType.Email
            ),
            modifier = Modifier
                .fillMaxWidth()
                .padding(top = 10.dp)
        )
    }
}
class LoginScreenViewModel():ViewModel() {
    var emailText by mutableStateOf("a")
    var passwordText by mutableStateOf("")
    var isVisibilityOn by mutableStateOf(false)

    lateinit var mAuth:FirebaseAuth

    private lateinit var navController: NavHostController
    private lateinit var context: Context

    constructor(navController: NavHostController,context:Context) : this() {
        this.navController=navController
        this.context=context
    }
}

Someone
  • 21
  • 4
  • 1
    Use viewModel function to obtain an instance of your viewmodel inside composables. You need to create a factory to pass parameters to viewmodel. Take a look: https://stackoverflow.com/a/67982296/17787605 – bylazy May 18 '22 at 10:20
  • Follow view model [documentation](https://developer.android.com/jetpack/compose/libraries#viewmodel) – Phil Dukhov May 18 '22 at 10:33

1 Answers1

1

var viewModel=LoginScreenViewModel(navController = navController, LocalContext.current)

Well, because you are not using val viewModel = remember { ViewModelProvider(LocalViewModelStore.current, object: ViewModelProvider.Factory { override fun <T: ViewModel> create(clazz: Class<T>) = LoginScreenViewModel(navController) } }).get(LoginScreenViewModel::class.java) } to get the reference to your ViewModel.

Although you can greatly reduce that with just calling = viewModel(factory = /* factory */).

Then again, you can't directly pass a NavController reference to a ViewModel, you'd need to use a channel and a DisposableEffect/LaunchedEffect to send commands from ViewModel to a NavController.

EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428