【发布时间】:2021-11-17 12:48:12
【问题描述】:
当列表数据存储在拥有列表小部件的同一组件中时,我能够在 Flutter 中成功地为 AnimatedList 的内容制作动画(即,当列表数据发生更改时不会发生重建)。当我尝试使用 Provider 和 Consumer 从 ChangeNotifier 获取列表项目时遇到问题。
拥有AnimatedList 的组件,我们称之为ListPage,是用Consumer<ListItemService> 构建的。我的理解是,只要服务更新列表数据并调用notifyListeners(),就会重建ListPage。发生这种情况时,我不确定在ListPage 内的哪个位置我可以调用AnimatedListState.insertItem 来为列表设置动画,因为在build 期间,列表状态仍然是null。结果是一个不为其内容设置动画的列表。
我认为我的问题归结为“如果实时获取和更新内容,我如何管理此列表的状态?”,理想情况下,我想了解发生了什么,但我愿意接受建议如果这不是完成任务的最佳方式,我应该如何改变它。
下面是一些说明问题的代码:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider<AuthService>(
create: (_) => AuthService(),
),
ChangeNotifierProxyProvider<AuthService, ListItemService>(
create: (_) => ListItemService(),
update: (_, authService, listItemService) =>
listItemService!..update(authService),
),
],
child: MaterialApp(
home: HomePage(),
),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Consumer<ListItemService>(
builder: (context, listItemService, _) =>
ListPage(items: listItemService.items),
);
}
}
// Implementation details aren't really relevant, but
// this only updates if the user logs in or out.
class AuthService extends ChangeNotifier {}
class ListItemService extends ChangeNotifier {
List<Item> _items = [];
List<Item> get items => _items;
Future<void> update(AuthService authService) async {
// Method that subscribes to a Firestore snapshot
// and calls notifyListeners() after updating _items.
}
}
class Item {
Item({required this.needsUpdate, required this.content});
final String content;
bool needsUpdate;
}
class ListPage extends StatefulWidget {
const ListPage({Key? key, required this.items}) : super(key: key);
final List<Item> items;
@override
_ListPageState createState() => _ListPageState();
}
class _ListPageState extends State<ListPage> {
final GlobalKey<AnimatedListState> _listKey = GlobalKey();
late int _initialItemCount;
@override
void initState() {
_initialItemCount = widget.items.length;
super.initState();
}
void _updateList() {
for (int i = 0; i < widget.items.length; i++) {
final item = widget.items[i];
if (item.needsUpdate) {
// _listKey.currentState is null here if called
// from the build method.
_listKey.currentState?.insertItem(i);
item.needsUpdate = false;
}
}
}
@override
Widget build(BuildContext context) {
_updateList();
return AnimatedList(
key: _listKey,
initialItemCount: _initialItemCount,
itemBuilder: (context, index, animation) => SizeTransition(
sizeFactor: animation,
child: Text(widget.items[index].content),
),
);
}
}
【问题讨论】:
-
顺便说一句,我看过这个问题,但我的控制流向相反。在问题中,拥有
AnimatedList的组件决定何时删除元素;在我的应用程序中,该组件只是在等待更新(即使它确实添加了元素,它也会通过告诉提供者应该添加一个项目然后监听来自 Firestore 的更改来做到这一点):stackoverflow.com/questions/61816446/…