起初是用户star和unstar的操作,逻辑代码写的都很顺利,
FloatingActionButton(
onPressed: () {
BlocProvider.of<PictureBloc>(context)
.add(StarEvent(state.illusts));
},
child: Icon(Icons.star),
foregroundColor:
state.illusts.isBookmarked ? Colors.red : Colors.white))
bloc
if (!event.illusts.isBookmarked) {
try {
Response response =
await client.postLikeIllust(event.illusts.id, "public", null);
yield DataState(event.illusts..isBookmarked=true);
} catch (e) {}
} else {
try {
Response response = await client.postUnLikeIllust(event.illusts.id);
yield DataState(event.illusts..isBookmarked=false);
} catch (e) {}
}
这一部分是写在BlocBuilder里的,照理来说,当我在Bloc里yield了新的state,那么按钮的color就会刷新
结果我发现,他永远都只会执行第一次的变化
找了半天设定上的问题和issue以及文档,发现BlocBuilder有个condition的属性
/// Signature for the condition function which takes the previous [state] and the current [state]
/// and is responsible for returning a [bool] which determines whether or not to rebuild
/// [BlocBuilder] with the current [state].
typedef BlocBuilderCondition<S> = bool Function(S previous, S current);
我注意到,这里的设计是为了判断是否需要rebuild组件里的内容
猜想,会不会是因为它内部的逻辑代码判断,我的illust指针指的是同一个内存地址,他判断prop是同等的,所以不给rebuild?
于是我重新实例化了一个Illusts对象,然后event.illusts拷贝过来,把新的对象作为实参prop传给state,果然大功告成
Illusts illusts = Illusts.fromJson(event.illusts.toJson());
illusts.isBookmarked = true; //降智时间
yield DataState(illusts);
踩坑成功,顺便吐槽一些似乎dart并没有比较方便的clone对象的功能
更新
也可将DataState继承的BaseState实现的equatable去掉,就不会对props内容进行对比,不过官方doc并不推荐这种做法