Home > other >  How can I share viewmodel from one screen to another screen in jetpack compose?
How can I share viewmodel from one screen to another screen in jetpack compose?

Time:04-18

I am try to learning android jetpack compose, and I have simple app. In ScreenA I have a text field and when I click the button, I am save this data to firestore, and when I come in ScreenB, I want to save city name also in firebase, but I am using one viewmodel, so how can save both text field data in the same place in firestore, I did not find any solution.

ScreenA:

    class ScreenAActivity : ComponentActivity() {



    private lateinit var  viewModel: MyViewModel

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)
     
        viewModel = ViewModelProvider(this)[MyViewModel::class.java]


        setContent {
            ScreenA(viewModel)
        }
     }
   }

  @Composable
  fun ScreenA(

  viewModel : MyViewModel

  ) {

   val name = remember { mutableStateOf(TextFieldValue()) }

      OutlinedTextField(
            value = name.value,   
            onValueChange = { name.value = it },
            label = { Text(text = "name") },
          
        )

        Button(
            modifier = Modifier
                .width(40.dp)
                .height(20.dp),
            onClick = {

                focus.clearFocus(force = true)
                viewModel.onSignUp(
                    name.value.text,
                 
                )
                context.startActivity(
                    Intent(
                        context,
                        ScreenB::class.java
                    )
                )

                },
            colors = ButtonDefaults.buttonColors(
                backgroundColor = Color.Red
            ),
            shape = RoundedCornerShape(60)
        ) {
            Text(
                text = "OK"
             
             )
            )
        }

 }

ScreenB:

class ScreenBActivity : ComponentActivity() {

override fun onCreate(savedInstanceState: Bundle?) {

    super.onCreate(savedInstanceState)

    setContent {
        ScreenB()
    }
 }
}

@Composable
fun ScreenB(

 ) {
val city = remember { mutableStateOf(TextFieldValue()) }

  OutlinedTextField(
        value = city.value,   
        onValueChange = { city.value = it },
        label = { Text(text = "city") },
      
    )

    Button(
        modifier = Modifier
            .width(40.dp)
            .height(20.dp),
        onClick = {

            focus.clearFocus(force = true)
            viewModel.onSignUp(
                city.value.text,
             
            )
           

            },
        colors = ButtonDefaults.buttonColors(
            backgroundColor = Color.Red
        ),
        shape = RoundedCornerShape(60)
    ) {
        Text(
            text = "OK"
         
         )
        )
    }

   }

CodePudding user response:

The recommendation is use a single activity and navigate through screens using Navigation library.

After you've refactored your code to use the Navigation library, you can pass the previous back stack entry in order to get the same instance of the View Model.

val navController = rememberNavController()
NavHost(
    navController = navController,
    ...
) { 
    composable("ScreenA") { backStackEntry ->
        val viewModel: MyViewModel = viewModel(backStackEntry)
        ScreenA(viewModel)
    }
    composable("ScreenB") { backStackEntry ->
        val viewModel: MyViewModel = viewModel(navController.previousBackStackEntry!!)
        ScreenB(viewModel)
    }
} 

But if you really need to do this using activity, my suggestion is define a shared object between the view models. Something like:

object SharedSignInObject {
    fun signUp(name: String) {
        // do something
    }
    // other things you need to share...
}

and in your viewmodels you can use this object...

class MyViewModel: ViewModel() {
    fun signUp(name: String) {
        SharedSignInObject.signUp(name)
    }
}
  • Related