In my app, I have some interdependent objects.
UiPreferences and Authentication both depend on DeviceRegistration. I have blocs for all three.
When the app launches, I have to get an existing - or create a new - DeviceRegistration. Nothing can really happen until I have this object.
This is an async process, so I can't put it the constructor of the bloc or in the initialState method.
I use listen statements in the UiPreferences and Authentication blocs to detect changes in the DeviceRegistration state. These changes will trigger changes in those blocs.
So here's my approach, but it seems a little hacky and not consistent with the architecture of flutter_bloc. I guess I'm asking if there's a better way...
In main I get or create the DeviceRegistration which I pass into the constructor of the DeviceRegistrationBloc. It looks like this:
DeviceRegistration deviceRegistration;
@override
DeviceRegistrationState get initialState =>
DeviceRegistrationLoaded(deviceRegistration: deviceRegistration);
DeviceRegistrationBloc(this.deviceRegistration);
I then create the UiPreferences and Authentication blocs, passing in the DeviceRegistrationBloc. That looks like this:
String _deviceRegistrationId;
final DeviceRegistrationBloc deviceRegistrationBloc;
AuthenticationBloc({this.deviceRegistrationBloc}) {
_deviceRegistrationId = deviceRegistrationBloc.deviceRegistration.id;
_deviceRegistrationStream = deviceRegistrationBloc.state.listen(
(state) async {
if (state is DeviceRegistrationUpdated) {
// we need to update the cloud...
}
},
);
}
I am getting the initial deviceRegistrationId which I need for logging in and I have the deviceRegistrationBloc for listening to other events.
One of the tricky parts here is that I can't authenticate without a deviceRegistrationId and I can only register the deviceRegistration in the cloud if I am authenticated. That's how I can create one, get a (semi) permanent id and use that to login. Later, using RxDart zip I can update the deviceRegistration in the cloud after I've authenticated.
Full disclosure, I wrote the entire thing using events and states and blocs in their pure form. But it became quite complicated to manage the relationships between all the objects. Forcing the deviceRegistration to actually be available when the other blocs were constructed turned out to simplify things. Is the new approach all wrong? Is this going to bite me at some point?
TIA
OK, ignore this. Sorry for the interruption.
Hey, i'm actually having the same problem of setting initialState based on an asynchronous function. What was your solution @nhwilly?
answer is simple, don't.
your initial state should be fast to create.
you can dispatch an event to move from initial state to another state based on that asynchronous function
I see. Thank you!
@theweiweiway I can't remember exactly (I had to step away to work on the back end for a couple of months), but I think @bigworld12 has it right.
I ended up with dependent blocs listening to other blocs and simply dispatched something to the DeviceRegistrationBloc to load it up. The other blocs picked up the change when the DeviceRegistrationBloc issued a DeviceRegistrationLoaded message. It seems really ugly at first, but after a minute you really how freeing it is. You just have to think through all the dependencies up front.
I also changed the back end to just get whatever the client sends it and decide what to do about it later. Turned out OK in the end.
Most helpful comment
OK, ignore this. Sorry for the interruption.
noprogrammingwhentired.