我有一個List<Data>顯示在一個ListView使用 Riverpod 來觀察串列的任何變化的。當我從該串列中添加或洗掉專案時,會ListView按預期進行重建,但看起來每個ListViewItem及其下降的小部件都在重建 - 即使它們顯示與以前相同的內容。這是我的代碼的簡化版本:
class MyApp extends ConsumerWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final listLength = ref.watch(dataLengthProvider);
return MaterialApp(
home: Scaffold(
body: Column(
children: [
ElevatedButton(
child: const Icon(Icons.add),
onPressed: () => ref.read(dataListProvider.notifier).add(),
),
Expanded(
child: ListView.builder(
itemCount: listLength,
itemBuilder: (context, index) {
return MyListItem(index);
},
),
),
],
),
),
);
}
}
class MyListItem extends ConsumerWidget {
final int index;
const MyListItem(this.index, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final countValue =
ref.watch(dataItemProvider(index).select((dataItem) => dataItem.value));
return Text('Value: ${countValue.toString()}');
}
}
// Providers -------------------------------------------------------------------
final dataListProvider = StateNotifierProvider<DataListNotifier, List<Data>>(
(ref) => DataListNotifier());
final dataLengthProvider =
Provider<int>((ref) => ref.watch(dataListProvider).length);
final dataItemProvider = Provider.family<Data, int>(
(ref, index) => ref.watch(dataListProvider)[index]);
// Notifier --------------------------------------------------------------------
class DataListNotifier extends StateNotifier<List<Data>> {
DataListNotifier() : super([const Data(), const Data()]);
void add() {
state = [...state, const Data(value: 0)];
}
}
// Data model ------------------------------------------------------------------
@immutable
class Data {
final int value;
const Data({this.value = 0});
Data copyWith({int? newValue}) => Data(value: newValue ?? value);
}
現在我的問題是:Flutter 是否足夠聰明,可以自動重用那些未更改的小部件?
如果沒有,我該怎么做才能避免不必要的構建?
uj5u.com熱心網友回復:
你可以檢查一些東西。為此,請重新創建您的類MyListItem以訪問 dispose():
class MyListItem extends ConsumerStatefulWidget {
final int index;
const MyListItem(
this.index, {
Key? key,
}) : super(key: key);
@override
ConsumerState createState() => _MyListItemState();
}
class _MyListItemState extends ConsumerState<MyListItem> {
@override
Widget build(BuildContext context) {
print(widget.index);
final countValue = ref.watch(
dataItemProvider(widget.index).select((dataItem) => dataItem.value));
return Text('Value: ${countValue.toString()}');
}
@override
void dispose() {
print('dispose: ${widget.index}');
super.dispose();
}
}
delete()并在附近添加方法add():
void delete() {
state.removeLast();
state = List.of(state);
}
并添加按鈕MyApp:
ElevatedButton(
child: const Icon(Icons.delete),
onPressed: () => ref.read(dataListProvider.notifier).delete(),
),
并再次檢查此代碼。當然,在那里RangeError (index)會引發錯誤,但這不是重點。但另一方面,您可以看到dispose()添加元素時沒有呼叫該方法,這意味著該物件沒有從樹中洗掉。同時,當最后一個元素被移除時,我們可以看到對dispose()方法的呼叫,但只針對最后一個元素!所以你在正確的軌道上:)
uj5u.com熱心網友回復:
您可以使用select獲取提供程式的參考,以停止串列項中不必要的重建。
https://riverpod.dev/docs/concepts/reading/#using-select-to-filter-rebuilds
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/516455.html
標籤:扑列表显示河荚
上一篇:KotlinAndroidNavigationtoFragment在setOnItemClickListener中不起作用
