bloc icon indicating copy to clipboard operation
bloc copied to clipboard

Question [hydrated_bloc] sophisticated example

Open II11II opened this issue 3 years ago • 10 comments

Firstly, I would like to thank the creator @felangel and contributors to these packages.

I would like to ask to add one sophisticated example usage of hydrated bloc according to the real problem( Manage to save categories to local database using hydrated bloc)

As known, nowadays numerous applications demands complicated feature (such as saving categories and its subcategories locally). Adding this kind of example will help developers to use hydrated bloc correctly.

Real-world API example: "some_url/category/getRoot" will return this kind of response "some_url/category/${id}" will return subcategories of that catgories


[
  {
        "name_of_category":"Some categories"
        "iconHashId": "ZjEv2eRa1",
        "id": 46
    },  
    {
        "name_of_category":"Some categories"
        "iconHashId": "ZjEv2eRa1",
        "id": 67
    },

]

After getting these details, it should be saved locally using a hydrated bloc.

It would be nice if you add example which shows how to properly use Hydrated bloc

II11II avatar Apr 15 '21 17:04 II11II

Hi @II11II 👋 Thanks for opening an issue!

The latest version of the weather app is using hydrated_bloc to cache the weather information so that it is available offline. Is there something in particular that you're having trouble achieving? I think the weather app should provide a good overview of how you could use hydrated_bloc to accomplish what you're asking for. Thanks 🙏

felangel avatar Apr 19 '21 02:04 felangel

Hi @felangel 🖐,

Yes, there are some trouble to save nested data using hydrated bloc.

The example of dilemma i provided above.

II11II avatar Apr 19 '21 09:04 II11II

Here example: Feature as Developer should create using hydrated bloc https://vimeo.com/539327490

II11II avatar Apr 20 '21 19:04 II11II

Here example: Feature as Developer should create using hydrated bloc https://vimeo.com/539327490

Is there a code example?

kovacbb avatar Apr 20 '21 22:04 kovacbb

@felangel What if I have multiple states (that extends from a parent state) with different properties. Can I use hydrated_bloc in that case, or I have to stick to the parent state and wrap all the properties inside that?

minhdanh avatar Jul 28 '21 14:07 minhdanh

@felangel What if I have multiple states (that extends from a parent state) with different properties. Can I use hydrated_bloc in that case, or I have to stick to the parent state and wrap all the properties inside that?

You can still use HydratedBloc in that case. You just need to adjust the toJson and fromJson implementations to check the type of the state and perform the correct (de)serialization.

felangel avatar Jul 28 '21 14:07 felangel

In case @II11II or anyone else may be helped by this: The way i started to prefer using hydrated_bloc for complex use cases & state classes is by:

  1. storing the state class name state.runtimeType.toString() in the toJson() method of each child state class.
  2. making a factory public fromJson() in the parent abstract state class, which will call specific child constructors based on the string state value stored in step 1.
  3. if there are any variables defined in the abstract parent class, i also make a private fromJson() in the parent abstract class, which will set it's values , and will be called with :super._fromJson() in the child state classes.

this way i can use one-liners for fromJson() and toJson() in the cubit class, deferring the specifics to the state classes, can define variables in abstract parent state classes, and also can not repeat code and variables in child constructors.

evanholt1 avatar Sep 06 '21 07:09 evanholt1

In case @II11II or anyone else may be helped by this: The way i started to prefer using hydrated_bloc for complex use cases & state classes is by:

  1. storing the state class name state.runtimeType.toString() in the toJson() method of each child state class.
  2. making a factory public fromJson() in the parent abstract state class, which will call specific child constructors based on the string state value stored in step 1.
  3. if there are any variables defined in the abstract parent class, i also make a private fromJson() in the parent abstract class, which will set it's values , and will be called with :super._fromJson() in the child state classes.

this way i can use one-liners for fromJson() and toJson() in the cubit class, deferring the specifics to the state classes, can define variables in abstract parent state classes, and also can not repeat code and variables in child constructors.

You idea show some promise @evanholt1. Can you please provide any example you used this approach? I'd really appreciate 🙂

mathiasgodwin avatar Mar 24 '22 17:03 mathiasgodwin

Hi @II11II wave Thanks for opening an issue!

The latest version of the weather app is using hydrated_bloc to cache the weather information so that it is available offline. Is there something in particular that you're having trouble achieving? I think the weather app should provide a good overview of how you could use hydrated_bloc to accomplish what you're asking for. Thanks pray

Hello, @felangel , I'm also looking for a more detailed example of using Hydrated bloc. Unlike the Weather App, where you should press a button to fetch data, my app needs to load its data right after a user sees the screen. I.e. I need to add an event right after creating a bloc:

create: (context) => getIt<TaskWatcherBloc>()
 ..add(const TaskWatcherEvent.watch(TaskStatusFilter.all))

I faced a problem that adding this event overrides the cached state. But if ..add(...) removed there will be nothing to show when storage is empty. Can you help and tell me what should I do?

You can reproduce the situation by adding ..fetchWeather("Chicago"), after creating WeatherCubit in the WeatherPage of  the Weather App. Then choose another city, hot restart the app and you'll see Chicago weather again.

Thank you.

tanyapog avatar May 17 '22 14:05 tanyapog

Hello, @felangel , I'm also looking for a more detailed example of using Hydrated bloc. Unlike the Weather App, where you should press a button to fetch data, my app needs to load its data right after a user sees the screen. I.e. I need to add an event right after creating a bloc:

It was not that difficult, actually, heh. I solved it by adding an Initiate event and checking storage by token. In view:

BlocProvider(
      create: (context) => getIt<TaskWatcherBloc>()
        ..add(const TaskWatcherEvent.initiate()),

In bloc:

on<TaskWatcherEvent>(
      (event, emit) async {
        await event.map(
          initiate: (event) {
            final token = super.storageToken;
            if (HydratedBlocOverrides.current!.storage.read(token) != null) {
              return;
            } else {
              add(const TaskWatcherEvent.watch(TaskStatusFilter.all));
            }
          },
          watch: (event) async {
            .....
          }
        );
      },
      transformer: restartable(),
    );

tanyapog avatar May 18 '22 12:05 tanyapog

@felangel What if I have multiple states (that extends from a parent state) with different properties. Can I use hydrated_bloc in that case, or I have to stick to the parent state and wrap all the properties inside that?

You can still use HydratedBloc in that case. You just need to adjust the toJson and fromJson implementations to check the type of the state and perform the correct (de)serialization.

How to check/access the type of the saved state. Do I have to write it in the json by myself? Or is it somewhere already saved?

Edit: For now I just write it in the json by myself. If there is a better way, please let me know.

talionderhobbit avatar Sep 28 '22 03:09 talionderhobbit

Closing this for now since this issue is quite old and there are many examples in the wild of hydrated_bloc. Feel free to file a new issue if you feel something is missing, thanks!

felangel avatar Oct 14 '23 21:10 felangel