为啥 AnimatedList 在颤动中不使用 bloc 状态的列表构建?
Posted
技术标签:
【中文标题】为啥 AnimatedList 在颤动中不使用 bloc 状态的列表构建?【英文标题】:Why is AnimatedList not building using list from bloc state in flutter?为什么 AnimatedList 在颤动中不使用 bloc 状态的列表构建? 【发布时间】:2021-10-01 20:08:52 【问题描述】:我正在尝试使用bloc
模式创建AnimatedList
,但遇到了一些问题。
当我将 AnimatedList
的 initialItemsCount 设置为 state.itemList.length
时,它不会构建。虽然当我在BlocConsumer
的监听器中打印出state.itemList
(来自ListBloc
)时,它会打印出itemList
。
那么,问题是为什么这不起作用?
我尝试对ListView.builder
做同样的事情,它工作正常。我是否遗漏了什么,或者 AnimatedList
甚至不应该使用 bloc 工作?
这里有一些示例代码,在这种情况下非常简单:
MyApp 类:
class _MyAppState extends State<MyApp>
final key = GlobalKey<AnimatedListState>();
@override
Widget build(BuildContext context)
return BlocProvider(
create: (context) => ListBloc()..add(LoadList()),
child: MaterialApp(
home: SafeArea(
child: BlocConsumer<ListBloc, ListState>(
listener: (_, state)
print(state.itemList);
,
builder: (context, state) => Scaffold(
body: Column(
children: [
Expanded(
child: AnimatedList(
key: key,
initialItemCount: state.itemList.length,
itemBuilder: (context, index, animation)
return Item(
animation: animation,
index: index,
text: state.itemList[index],
onTap: () => removeItem(index, state.itemList));
,
),
),
],
),
),
),
),
),
);
void removeItem(int index, List<String> items)
final item = items.removeAt(index);
key.currentState?.removeItem(
index,
(context, animation) => Item(
animation: animation,
index: index,
text: items[index],
onTap: () => removeItem(index, items)));
物品类别:
class Item extends StatelessWidget
final Animation<double> animation;
final int index;
final String text;
final VoidCallback onTap;
const Item(
required this.animation,
required this.index,
required this.text,
required this.onTap,
Key? key)
: super(key: key);
@override
Widget build(BuildContext context)
return ScaleTransition(
scale: animation,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
onTap: onTap,
child: Container(
color: Colors.blue,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(text),
),
)),
),
);
集团:
class ListEvent extends Equatable
const ListEvent();
@override
List<Object> get props => [];
class LoadList extends ListEvent
class ListState extends Equatable
final List<String> itemList;
const ListState(required this.itemList);
@override
List<Object> get props => [itemList];
class ListBloc extends Bloc<ListEvent, ListState>
ListBloc() : super(ListState(itemList: []));
@override
Stream<ListState> mapEventToState(ListEvent event) async*
if (event is LoadList)
var items = ['1', '2', '3', '4', '5', '6'];
yield ListState(itemList: items);
谢谢!
【问题讨论】:
【参考方案1】:我在 AnimatedList 中遇到过类似的场景,即 itemBuilder 的调用方式和列表的重建方式。
如果您在 AnimatedList 小部件(即您的父 Expanded 小部件)上方和 itemBuilder 调用中设置断点,您可能会注意到在某些情况下 itemBuilder 正在执行而第一个断点未命中.
这看起来是因为 AnimatedList 的动画特性导致 itemBuilder 被直接调用为框架页面刷新的一部分(在包含的小部件之外,例如您的 BlocConsumer,因此您的状态尚未按预期设置)。
【讨论】:
以上是关于为啥 AnimatedList 在颤动中不使用 bloc 状态的列表构建?的主要内容,如果未能解决你的问题,请参考以下文章
iCheck 复选框在颤动的 Android 网络视图中不起作用
方向性(textDirection:TextDirection.rtl,)在颤动中不起作用