我很困惑,Nested ProviderScope 和所有 Providers 是否会从内存中删除?遵循用例是好的实践还是坏的实践?
我有idsProvider
final idsProvider = Provider((_) => List.generate(50, (i) => i));
并为 idsProvider 的每个 id 提供 itemIdProvider
final itemIdProvider = Provider.autoDispose((_) => 0);
界面如下:
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()),
);
}
}
然后我有 stateNotifierProvider 来操作 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;
}
我认为这是完全可以接受的。另外,你可能没有初始值:
final itemIdProvider = Provider.autoDispose((_) => throw UnimplementedError());
这样就可以看到该值稍后会被实现。
关于记忆。
ProviderScope
是一个 StatefulWidget
,并且在“引擎盖”下有以下代码行:
@override
void dispose() {
container.dispose();
super.dispose();
}
所以你不用太担心:)