简体   繁体   中英

Jetpack Compose state change not reflected across activities

I have an app with two activities. Activity1 changes a State stored in a ViewModel , then starts Activity2 . But somehow, the state change is only reflected in Activity1 , not in Activity2 .

ViewModel

class MyViewModel : ViewModel() {
    var hasChanged: Boolean by mutableStateOf(false)
}

Composable of Activity1

@Composable
fun Screen1() {

    val context = LocalContext.current
    val viewModel: MyViewModel = viewModel()

    Column {
        Text("State changed: " + viewModel.hasChanged.toString())
        Button(
            onClick = {
                viewModel.hasChanged = true
                startActivity(context, Intent(context, Activity2::class.java), null)
            }
        ) {
            Text("Change State!")
        }
    }
}

Composable of Activity2

@Composable
fun Screen2() {
    val viewModel: MyViewModel = viewModel()
    Text("State changed: " + viewModel.hasChanged.toString())  # stays 'false'
}

Behavior of the app

  • Activity1 correctly shows the state to be false , initially
  • After button is pressed, Activity1 correctly displays the state to be true
  • Activity2 opens but still shows the state to be false

Question

Why is the state change not reflected in Activity2 and can this be fixed?

ViewModels are unique to classes that implement ViewModelStoreOwner

@Composable
public inline fun <reified VM : ViewModel> viewModel(
    viewModelStoreOwner: ViewModelStoreOwner = checkNotNull(LocalViewModelStoreOwner.current) {
        "No ViewModelStoreOwner was provided via LocalViewModelStoreOwner"
    },
    key: String? = null,
    factory: ViewModelProvider.Factory? = null,
    extras: CreationExtras = if (viewModelStoreOwner is HasDefaultViewModelProviderFactory) {
        viewModelStoreOwner.defaultViewModelCreationExtras
    } else {
        CreationExtras.Empty
    }

ComponentActivity implements ViewModelStoreOwner , so it's a ViewModelStoreOwner that contains its own ViewModel instances and uses a HashMap to get same ViewModel for key provided as String.

val vm: MyViewModel = ViewModelProvider(owner = this)[MyViewModel::class.java]

This is how they are created under the hood. This here is Activity or Fragment depending on where ViewModelProvider's owner param is set at. In Compose ViewModelStore owner is accessed by LocalViewModelStoreOwner.current

You need to pass your hasChanged between Activities using Bundle , or have a Singleton repository or UseCase class that you can inject to both ViewModels or use local db or another methods to pass data between Activities.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM