Flutter State Restoration of ListView or BLoC

1.1k Views Asked by At

I'm trying to restore my listview widget after android kills my app from memory by using RootRestorationScope:

runApp(RootRestorationScope(
     child: MaterialApp(home: MyApp()),
     restorationId: "root",
  ));

and making my own restorable widget using extends RestorableValue:

class RestorableListBloc extends RestorableValue<ListBloc> {
  @override
  ListBloc createDefaultValue() {
    return ListBloc(
      repository: Repository(),
    )..add(
        Fetch(),
      );
  }

  @override
  void didUpdateValue(ListBloc oldValue) {
    if (oldValue.state != value.state) {
      notifyListeners();
    }
  }

  @override
  ListBloc fromPrimitives(Object data) {
    print('data: ' + data);
    return ListBloc(repository: data);
  }

  @override
  Object toPrimitives() {
    return value.repository;
  }
}

Where ListBloc is a Bloc that controls what's in my listview widget (collection of timers right now in case anyone's curious).

I extend the class with the restoration mixing and call the bloc inside of a multibloc providers widget as follows:

class _MyAppState extends State<MyApp> with RestorationMixin {
  SpeedDialGenerator speedDial = SpeedDialGenerator();
  RestorableListBloc _test = RestorableListBloc();
  final assetsAudioPlayer = AssetsAudioPlayer();

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (BuildContext context) => DrawerCubit(value: false),
      child: Scaffold(
        backgroundColor: Colors.blue[50],
        drawer: SafeArea(
          child: AppDrawer(),
        ),
        appBar: AppBar(
          backgroundColor: Colors.blue[900],
          title: Text('Myapp'),
          centerTitle: true,
          actions: [
            IconButton(
              icon: Image.asset('assets/images/myapp_white.png'),
              onPressed: () {},
            ),
          ],
        ),
        body: Stack(children: [
          HourglassBackground(),
          MultiBlocProvider(
              providers: [
                BlocProvider(
                  create: (context) => _test.value,
                ),
                BlocProvider(
                  create: (context) => AppStateCubit(),
                )
              ],
              child: BlocBuilder<ListBloc, ListState>(
                builder: (context, state) {
                  if (state is Failure) {
                    return Center(
                      child: Text('Oops something went wrong!'),
                    );
                  }
                  if (state is Loaded) {
                    return Stack(children: [
                      HomePage(state: state, displayNotification: () => {}),
                      Padding(
                        padding: EdgeInsets.fromLTRB(0, 0, 10, 10),
                        child: BlocProvider(
                            create: (context) => TimerpopupCubit(),
                            child: speedDial.buildSpeedDial(context)),
                      ),
                    ]);
                  }
                  return Center(
                    child: CircularProgressIndicator(),
                  );
                },
              )),
        ]),
      ),
    );
  }

  @override
  String get restorationId => 'root';

  @override
  void restoreState(RestorationBucket oldBucket, bool initialRestore) {
    registerForRestoration(_test, restorationId);
  }

Unfortunately, everytime I run the app I get:

The following assertion was thrown building Builder:
'package:flutter/src/services/restoration.dart': Failed assertion: line 592 pos 12: 'debugIsSerializableForRestoration(value)': is not true.

There's not much documentation and I know this is a relatively new feature of flutter, but from what I gather this means that you can't currently restore a BLoC?

Is there a way around this or some other approach I should look at?

Thanks

1

There are 1 best solutions below

0
On

There are some approaches such as using HydratedBloc library that has built in feature to save its state.

Or you can implement your own local database and when user re run app, the repository returns first local data and returns remote one.