I have a small cart system. I want to maintain items added to the cart and for the person they are added for across screens.
But by the time i reach screen2, the viewmodel resets.
@HiltViewModel
class CartVM
@Inject
constructor() : ViewModel() {
private var orderInformation: OrderInformation by mutableStateOf(OrderInformation())
fun submitOrder() { }
fun getAllCartItems(): List<BasketItem> {
return orderInformation.cartItems.value
}
fun addItemToCart(basketItem: BasketItem) {
orderInformation.cartItems.value = orderInformation.cartItems.value.plus(basketItem)
}
}
my first screen which adds items to the cart and working well.
@Destination
@Composable
fun ShopScreen(
vm: CartVM = hiltViewModel(),
navigator: DestinationsNavigator? = null,
) {
val item = generateRandomItem();
Button(onClick= {vm.addItemToCart(item)}){Text(text="add to cart")}
Button(
onClick = {
//continue to cart
navigator?.navigate(CartScreenDestination)
},
) {
Text(
text = "Go To Cart",
modifier =
Modifier
.fillMaxWidth(),
textAlign = TextAlign.Center,
)
}
}
now when you click continue, it navigates to the following screen but the cart is empty.
@Composable
fun CartScreen(
vm: CartVM = hiltViewModel(),
navController: DestinationsNavigator,
) {
val cartItems = vm.getAllCartItems()
}
but cartItems is empty now. How come it doesn't maintain its list. The composables are under one roof with
@HiltAndroidApp
class App : Application() {}
What am i doing wrong? I thought @HiltViewModel makes the view model singleton and as long as i do CartVM: hiltViewModel(), i would get the same instance.
@HiltViewModel
does not making singletons, it's only help Hilt identify viewModels for injection, so you are making two instances of CartVM. Hilt has Singleton
annotation, but it's not applyable for viewModels. You have 2 options on how to solve it.
1. create one instance and share it through the screens
Sorry, i can't make example code because i don't know the navigation you are using.
2. Create singleton repository for holding data
ViewModel instances can share singleton repository where you will keep your data.
@Singleton
class CartRepo @Inject constructor() {
var orderInformation: OrderInformation by mutableStateOf(OrderInformation())
}
And use it like this:
@HiltViewModel
class CartVM @Inject constructor() : ViewModel() {
@Inject
lateinit var cartRepo: CartRepo
fun getAllCartItems(): List<BasketItem> {
return cartRepo.orderInformation.cartItems.value
}
fun addItemToCart(basketItem: BasketItem) {
cartRepo.orderInformation.cartItems.value =
cartRepo.orderInformation.cartItems.value.plus(basketItem)
}
}