Hello! In android I am using `StateKeeperProvider`...
# mvikotlin
s
Hello! In android I am using
StateKeeperProvider
to keep
Store
during configuration change. I do it as in the example:
stateKeeperProvider.retainStore (lifecycle) {...
But when I close the fragment and reopen it, I get the error “_The supplier is already register with this key: class com.example.MyStore_”. Shouldn’t the supplier unregister in such cases? And what should I do to avoid getting this error?
a
Hello! Could you please elaborate how do you close/reopen the fragment?
And in what place you are calling
retainStore(lifecycle)
?
s
Just
popBackStack
. I tried this with navigation-library as well as simple fragmentManager.
retainStore
I call in controller, just like in the example.
a
It's hard to say without code sample. But in general the error means that there is already a registered
key
for the
StateKeeperController
. In case of
retainStore(lifecycle)
the
key
is
YourStore::class.toString()
. Please make sure the
StateKeeperController
is not reused by the new instance of the fragment.
s
Do you mean
StateKeeperContainer
?
a
StateKeeperContainer
is a new thing, it is not yet released. It will go next release.
The next version will be a stable one "2.0.0", and it will bring breaking changes for StateKeeper API unfortunately.
Sorry, I confused. Yes I mean
StateKeeperContainer
And
StateKeeperController
is a replacement.
But nothing fundamentally new. Just reorganized interfaces a bit.
s
Hmm. Do I need to create a new
StateKeeperContainer
every time I want to reopen a fragment?
a
Please give me some time to double check
s
I thought it should exist in a single instance for the entire application and stored in the MainActivity 🤔
(Of course, speaking of SingleActivityApplication)
a
I will check, thanks for raising the question
Yes, you are right. There is no way to unregister from the
StateKeeper
. I will add it. Regarding the
StateKeeperContainer
instance - I think it still should be per fragment. Because the fragments have their own
onSaveInstanceState
callback and we should definitely use it, not the Activity's one.
s
The Activity has
lastCustomNonConfigurationInstance
, which we make as instance of
StateKeeperContainer
, and which allows
Stores
to be saved during a configuration change. I don’t understand how we can achieve the same in a fragment without involving Activity 🤔
It might be necessary to detect when a fragment dies permanently and call unregister on the supplier?
a
Yes, for
lastCustomNonConfigurationInstance
you have to use Activity, and here you will need the upcoming fix. For state preservation over process death we should use Fragment's onSaveInstanceState()
s
Okay thanks 🙂 I will wait for this fix 🙃 I will also be grateful for an example of use. Probably need to call
unregister
manually? As far as I know, at the lifecycle callbacks level, it is impossible to distinguish between closing a fragment and re-creating it during a configuration change.
Although, I think using the navigation-library and its callbacks, it will be possible to bring this into one place without unnecessary inheritance or another boilerplate)
a
The
retainInstance
and so the
retainStore
methods will take care of unregistering.
s
Oh, interesting. I checked in the debugger, it distinguishes recreating from returning, great :)
a
I also came up with a solution using ViewModel. In this case there is a
StateKeeperProvider
instance per fragment instance. Actually the custom ViewModel implements
StateKeeperProvider
. Need to think about it.
Hey @Skeptick! I have submitted the PR with a solution. The idea is that both
StateKeeperController
and
StateKeeperProvider
should have separate instances per Fragment instance, so there is no need to unregister. I added some extensions which make everything automatically. Could you please check and let me know your thouths? https://github.com/arkivanov/MVIKotlin/pull/114
I will also add the ability to unregister in a separate PR.
s
Hi! Looks good and understandable! I am glad to get rid of the need to pass StateKeeperProvider from the Activity 😁
👍 1