Home > Blockchain >  Will ProviderScope and riverpod providers be removed from memory?
Will ProviderScope and riverpod providers be removed from memory?

Time:10-19

I am confused that will Nested ProviderScope and all Providers be romoved from memory? And is following usecase good practice or bad practice?

I have idsProvider

final idsProvider = Provider((_) => List.generate(50, (i) => i));

and have itemIdProvider for every id of idsProvider

final itemIdProvider = Provider.autoDispose((_) => 0);

UI as follows:

class BuildListView extends ConsumerWidget {
  const BuildListView({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final ids = ref.watch(idsProvider);

    return ListView.builder(
      itemCount: ids.length,
      itemBuilder: (context, index) {
        return ProviderScope(
          overrides: [
            itemIdProvider.overrideWithValue(ids[index]),
          ],
          child: const BuildItem(),
        );
      },
    );
  }
}

class BuildItem extends ConsumerWidget {
  const BuildItem({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final itemState = ref.watch(itemProvider);

    return itemState.when(
      data: (id, data) => ListTile(
        title: Text("ID: $id"),
        subtitle: Text(data),
      ),
      loading: () => const CircularProgressIndicator(),
      error: (error) => Text(error.toString()),
    );
  }
}

Then I have stateNotifierProvider to manipulate the state of every item of the ListView:

final itemProvider = StateNotifierProvider.autoDispose<ItemNotifier, ItemState>(
  (ref) => ItemNotifier(ref.watch(itemIdProvider)),
  dependencies: [itemIdProvider],
);

class ItemNotifier extends StateNotifier<ItemState> {
  ItemNotifier(this.id) : super(const ItemState.loading()) {
    fetchData();
  }

  final int id;

  Future<void> fetchData() async {
    await Future.delayed(const Duration(seconds: 2));
    if (mounted) {
      state = ItemState.data(id: id, data: "Data for $id");
    }
  }

  // A lot of methods to change the state
  // ...
  // ...
}

@freezed
class ItemState with _$ItemState {
  const factory ItemState.data({required int id, required String data}) = Data;

  const factory ItemState.loading() = Loading;

  const factory ItemState.error([String? message]) = Error;
}

CodePudding user response:

I think it's perfectly acceptable. In addition, you may not have an initial value:

final itemIdProvider = Provider.autoDispose((_) => throw UnimplementedError());

This way it will be seen that the value will be implemented later.

About memory. ProviderScope is a StatefulWidget and has the following lines of code under the 'hood':

@override
  void dispose() {
    container.dispose();
    super.dispose();
  }

So you don't have to worry too much :)

  • Related