I have the error "Cannot use "ref" after the widget was disposed", what's wrong?

143 Views Asked by At

I have a loading provider, and whenver I need to do an async work I set the loading state to true and at the finish time of asynchronous tasks I set it to false

but when I want to do so I get the error "Cannot use "ref" after the widget was disposed". what can I do to achieve the goal?

Here is my code :

final loadingProvider = StateProvider<bool>((ref) => false);


class GlobalLoading extends HookConsumerWidget {
  const GlobalLoading({required this.child, Key? key}) : super(key: key);

  final Widget child;

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final _entries = useState<List<OverlayEntry?>>([]);
    ref.listen(
      loadingProvider,
      (previous, next) {
        print(previous);
        print(next);
        if (previous == next) return;
        if (next) {
          // Add a modal barrier so the user cannot interact with the app while the loading indicator is visible
          _entries.value.add(OverlayEntry(
            builder: (_) =>
                ModalBarrier(color: AppColors.backGround.withOpacity(0.85)),
          ));
          _entries.value.add(OverlayEntry(
              builder: (_) => Center(
                      child: LoadingAnimationWidget.inkDrop(
                    color: AppColors.secondaries[1],
                    size: 160,
                  ))));
          Overlay.of(context).insertAll(Iterable.generate(
              _entries.value.length, (index) => _entries.value[index]!));
        } else {
          // Remove the modal barrier and loading indicator
          _entries.value.forEach((entry) => entry?.remove());
          _entries.value.clear();
        }
      },
    );
    return child;
  }
}


 GlobalLoading(
            child: SafeArea(
              minimum: EdgeInsets.only(top: height / 15),
              child: Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  // mainAxisSize: MainAxisSize.min,
                  children: [
                    TiTleTile(
                      title: info['nightNumber'] == '0'
                          ? nightNumber
                          : info['title']! + ' $nightNumber',
                    ),
                    SizedBox(height: height / 24),
                    Expanded(
                      child: SizedBox(
                        width: width / 1.5,
                        // height: height / 1.5,
                        child: ListView.separated(
                          shrinkWrap: true,
                          cacheExtent: height / 1.64,
                          restorationId: 'night-page',
                          clipBehavior: Clip.antiAlias,
                          // shrinkWrap: true,
                          // physics: RangeMaintainingScrollPhysics(),
                          itemCount: value.length,
                          itemBuilder: (_, index) {
                            print(value.elementAt(index).playerName!);

                            return Column(
                              crossAxisAlignment: CrossAxisAlignment.stretch,
                              children: [
                                if (value.elementAt(index).nightDone != true)
                                  PlayerNameWidget(
                                    playerName: value[index].playerName!,
                                    height: height,
                                    situation: info['situation']!,
                                    nightContext: nightContext,
                                  ),
                                if (value.elementAt(index).nightDone != true)
                                  SizedBox(
                                    height: height / 64,
                                  ),
                              ],
                            );
                          },
                          separatorBuilder: (BuildContext context, int index) {
                            if (value.elementAt(index).nightDone != true)
                              return SizedBox(height: height / 48);
                            return SizedBox();
                          },
                        ),
                      ),
                    ),

                    // spacer
                    if (info['button'] != null) SizedBox(height: height / 24),

                    if (info['situation'] == MyStrings.showRoles)
                      MyButton(
                          title: 'go to day',
                          onPressed: () async {
                            ref.read(loadingProvider.notifier).state = true;

                            final isar =
                                await ref.read(isarServiceProvider.future);

                            final yesterday = await isar.getDayNumber();

                            await isar.putGameStatus(
                              dayNumber: yesterday,
                              isDay: true,
                              situation: MyStrings.dayPage,
                            );

                            await ref
                                .read(currentPlayersProvider.notifier)
                                .action(MyStrings.dayPage);

                            nightContext.go('/day/$yesterday');
                            ref.read(loadingProvider.notifier).state = false;
                          }),

                    

....
More
....
....

Setting the loading provider's state to false & true But got the provided error

1

There are 1 best solutions below

6
bqubique On

For this a minimal reproducible code snippet would work for us, but generally speaking this is because the widget has been disposed and you're trying to use the ref when the widget itself was disposed. Some solutions include:

Setting a separate variable and saving it when the widget is disposed so as to keep it alive but Riverpod lint suggests not using ref inside dispose method.


(Preferred) use the mounted property to check if the widget is still mounted in the widget tree by:

if(mounted) return;
// * Use ref here as you wish as it is safe to call it here

OR

if(context.mounted) return;
// * Use ref here as you wish as it is safe to call it here

Riverpod FAQ has this covered: I have the error "Cannot use "ref" after the widget was disposed", what's wrong?