Alex
Alex

Reputation: 3

Using HydratedBloc -- LateInitilizationError Field '__storage@30190796' has not been initialized

I am trying to learn Flutter and Bloc/ HydratedBloc. I can't seem to get past an exception I keep getting when trying to save a value to local storage. I have tried creating this new simpler project, and have done a lot of troubleshooting, but I still get the same error:

'LateError (LateInitializationError: Field '__storage@30190796' has not been initialized.)'.

The exception occurs on the increment function in counter_state.dart.

main.dart:

import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:hydrated_bloc_debugging/counter/counter_cubit.dart';
import 'package:path_provider/path_provider.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  HydratedBloc.storage = await HydratedStorage.build(
    storageDirectory: HydratedStorageDirectory(
      (await getApplicationDocumentsDirectory()).path,
    ),
  );

  runApp(
    const MyApp(),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return BlocProvider<CounterCubit>(
      create: (context) => CounterCubit(),
      child: MaterialApp(
        home:
            const MyHomePage(), // Use a named route or a stateless widget here
      ),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Counter App'),
      ),
      body: Center(
        child: BlocBuilder<CounterCubit, CounterState>(
          builder: (context, state) {
            return Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                const Text(
                  'You have pushed the button this many times:',
                ),
                Text(
                  '${state.counterValue}',
                ),
              ],
            );
          },
        ),
      ),
      floatingActionButton: Row(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          FloatingActionButton(
            onPressed: () {
              context.read<CounterCubit>().increment();
            },
            tooltip: 'Increment',
            child: const Icon(Icons.add),
          ),
          FloatingActionButton(
            onPressed: () {
              context.read<CounterCubit>().decrement();
            },
            tooltip: 'Decrement',
            child: const Icon(Icons.remove),
          ),
        ],
      ),
    );
  }
}

counter_cubit.dart:

import 'package:equatable/equatable.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';

part 'counter_state.dart';

class CounterState extends Equatable {
  final int counterValue;

  const CounterState({
    required this.counterValue,
  });

  @override
  List<Object> get props => [counterValue];

  factory CounterState.fromMap(Map<String, dynamic> json) => CounterState(
        counterValue: json['counterValue'] as int,
      );

  Map<String, dynamic> toMap() {
    return {
      'counterValue': counterValue,
    };
  }
}

counter_state.dart:

part of 'counter_cubit.dart';

class CounterCubit extends Cubit<CounterState> with HydratedMixin {
  CounterCubit() : super(CounterState(counterValue: 0));

  void increment() => emit(
        CounterState(counterValue: state.counterValue + 1),
      );

  void decrement() => emit(
        CounterState(counterValue: state.counterValue - 1),
      );

  @override
  CounterState? fromJson(Map<String, dynamic> json) {
    return CounterState.fromMap(json);
  }

  @override
  Map<String, dynamic> toJson(CounterState state) => state.toMap();
}

I have spent way too much time trying to figure this out, so any help would be much appreciated!

Upvotes: 0

Views: 29

Answers (1)

Alex
Alex

Reputation: 3

Turns out this was actually a pretty simple fix. I didn't realize the hydrate() function had to be called in the construstor of all classes using HydrateMixin to populate the internal state storage with the latest state.

Upvotes: 0

Related Questions