'SavedStateHandle kotlin always receiving null
I need a Factory to support Viewmodel WITH ARGUMENTS. I tried to implement the class which is commended "AbstractSavedStateViewModelFactory". I applied the trouble in the short way.
I don't know if I am failing at ShopFragment. Some ideas please. I am working with HandleSavedState and a customizable ModelFactory which receive parameters, extending AbstractSavedStateViewModelFactory, but I am not currently be able to SAVE VALUE.
!! BY THE WAY: I don't know if this line(ShopFragment.kt) is correct:
ShopViewModelFactory(requireNotNull(requireActivity()).application, this, quantity, idupdate) maybe it is
I had tried harder but always receive null in Log. I don't want Inject dependencies with some responses that I have seen like "Hilt"
dependencies implementation "androidx.lifecycle:lifecycle-viewmodel-savedstate:2.5.0-alpha02"
ViewModelfactory.kt
class ShopViewModelFactory(
val application: Application,
val owner: SavedStateRegistryOwner,
val quantity: Int, val idupdate: Int
) : AbstractSavedStateViewModelFactory(owner, null){
override fun <T : ViewModel?> create( key: String, modelClass: Class<T>,
handle: SavedStateHandle ): T {
if (modelClass.isAssignableFrom(ShopViewModel::class.java)) {
@Suppress("UNCHECKED_CAST")
return ShopViewModel(application, handle, quantity,idupdate) as T
}
throw IllegalArgumentException("Unable to construct SHOPviewmodel")
}
}
In the Fragment: ShopFragment.kt
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? {
bind = DataBindingUtil.inflate(inflater, R.layout.fragment_shop, container, false)
var quantity = ShopFragmentArgs.fromBundle(requireArguments()).quantity
var idupdate = ShopFragmentArgs.fromBundle(requireArguments()).idproduct
var factory = ShopViewModelFactory(requireNotNull(requireActivity()).application,
this,
quantity,
idupdate)
vmShop =ViewModelProvider(this, factory).get(ShopViewModel::class.java)
In ShopViewModel.kt:
class ShopViewModel (application: Application,
private val savedStateHandle: SavedStateHandle,
quantity: Int, idupdate: Int): ViewModel() {
private val memoria2 : MutableLiveData<String> = savedStateHandle.getLiveData("user","init ")
init{
Log.i("DICE","RECUPERADO ${memoria2}")
addToCart()
}
private fun addToCart(){
memoria2.value += "Some data"
// that previous sentence suppose to save persist data
// !!if I add savedStateHandle.set("user", memoria2.value) still is not working
}
}
This supposed to initialize if savedInstanceState.value is null: savedStateHandle.getLiveData("user","init ")
Expected response:
a. I/DICE RECUPERADO init Some data
b. I/DICE RECUPERADO init Some data Some data
Solution 1:[1]
When you're using a SavedStateHandle and getLiveData for a particular key, you're not supposed to set the value on that LiveData - you're supposed to set it on the SavedStateHandle using the same key. That way, the data is stored, and the LiveData updates automatically (because getLiveData links it to the stored state)
So you want to do it this way:
private fun addToCart(){
savedStateHandle["user"] = "Some data"
}
and it should just work!
Remember that SavedStateHandles are lost when the app is explicitly closed. They only maintain the state while the app is running, so it can survive things like Activities getting destroyed, or the app getting closed in the background and recreated by the system - it's like savedInstanceState in an Activity or Fragment. If you need to store data between sessions, you need to persist it in something like SharedPreferences or a database
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | cactustictacs |
