Closed qhu91it closed 2 years ago
@qhu91it
In these cases, try to use InjectedFuture;
class LocalPref {
late SharedPreferences _prefs;
Future<LocalPref> initialized() async {
_prefs = await SharedPreferences.getInstance();
// add this line
return this;
}
...
}
final localPrefRM = RM.injectFuture<LocalPref>(
() => LocalPref().initialized(),
autoDisposeWhenNotUsed: false,
);
@GIfatahTH thank for your help, I try and got another error when homeVM dependsOn localPrefRM so localPrefRM not init finished => homeVM still waiting, then OnBuilder call initState (homeVM.state.initialized(args)) in SideEffects will throw error invalid arguments. Because in initialized func I pass some arguments so I can not declare at RM.inject
════════ Exception caught by widgets library ═══════════════════════════════════
The following ArgumentError was thrown building OnBuilder<Object?>:
Invalid argument(s) (
[HomeViewModel] is NON-NULLABLE STATE!
The non-nullable state [HomeViewModel] has null value which is not accepted
To fix:
1- Define an initial value to injected state.
2- Handle onWaiting or onError state.
3- Make the state nullable. (HomeViewModel?).
): Must not be null
@qhu91it Try not using dependsOn and instead use RM.injectedFuture and wait there for the localPrefRM to initialize:
final homeVM = RM.injectFuture<HomeViewModel>(
() async => HomeViewModel(
localPref: await localPrefRM.stateAsync,
...
),
);
Thanks, but it not solve my problem. I move to onSetState and it can work now
if (snap.data is HomeViewModel && snap.isIdle) {
final vm = (snap.data) as HomeViewModel;
vm.initialized(this);
return;
}
I got another problem, not sure it issue or not, I set autoDisposeWhenNotUsed is false but sometime later I see it Initializing again,
The situation is each view model use devicesRM, and have set devicesRM to dependsOn, when I push and pop page continuous, the view model dispose and somehow cause devicesRM dispose too. I remove devicesRM from dependsOn and not get this problem anymore.
Another question about injectFuture, if I get class I use like this await localPrefRM.stateAsync,
, but how about get ReactiveModel?
final homeVM = RM.injectFuture<HomeViewModel>(
() async => HomeViewModel(
localPref: localPrefRM, //<-- how to wait localPrefRM init finished here?
...
),
);
I got another problem, not sure it issue or not, I set autoDisposeWhenNotUsed is false but sometime later I see it Initializing again,
If autoDisposeWhenNotUsed is false the model should not dispose of. Could you give me a minimistic example reproducing this case.
Another question about injectFuture, if I get class I use like this await localPrefRM.stateAsync,, but how about get ReactiveModel? Just await for the stateAsync.
final homeVM = RM.injectFuture<HomeViewModel>(
() async {
await localPrefRM.stateAsync;
HomeViewModel(
localPref: localPrefRM, //<-- how to wait localPrefRM init finished here?
...
)
},
);
@GIfatahTH I create a demo to reproducing this case https://drive.google.com/file/d/1SjY48dFFW50XQpY6yKTNtnVOm_iw2KR1/view?usp=sharing
I describe this case:
Now swipe left to open side bar and tap to push page (button 'Go to List' or '+' or '-'), then pop page, you can see countersRM dispose called.
Another issue is when you push to counter page, and push a button to change counter in this page, and got error index not init... I see because counterVM depend on countersRM, so when countersRM reload and counterVM reload too but I think counterVM should not return default object.
Hi @qhu91it
Thanks for the example. I got your case.
The situation is each view model use devicesRM, and have set devicesRM to dependsOn, when I push and pop page continuous, the view model dispose and somehow cause devicesRM dispose too. I remove devicesRM from dependsOn and not get this problem anymore.
Yes, this is a bug. It will be fixed in the next release. Thanks again for reporting it.
Another issue is when you push to counter page, and push a button to change counter in this page, and got error index not init... I see because counterVM depend on countersRM, so when countersRM reload and counterVM reload too but I think counterVM should not return default object.
This behavior is expected. Because using dependsOn
and when countersRM
emits a notification the counterDecrementVM
will recall its creation function, thus creating a new instance of CounterDecrementViewModel
which will have a new index not initialized yet.
dependsOn
is meant to be used if the state is recalculated for other states.
You are using dependsOn
only to notify child views when countersRM
emits a notification. Just remove all dependsOn
and your example will work.
Hi @GIfatahTH, thank for explain about dependsOn
, I thought use dependsOn
just for wait all depend init completed :D
Follow code sample, it call when app start, because onInitialized func not finished yet so when func initialized call from homeVM got the error the _prefs is not init... I just want onInitialized of RM.inject can wait until finish before go to next or any suggest for this case?