我正在使用2个StreamBuilders(一个在另一个内)在App和App中进行构建。
最外面的一个消耗.Main-buttonWrapper
并渲染该列表。
内层消耗Stream<List<User>>
,在这里我可以检查用户是否喜欢。
代码如下:
users_page.dart
Stream<User>
users_block.dart
@override
Widget build(BuildContext context) {
return Scaffold(
child: StreamBuilder<List<User>>(
stream: userBloc.outList,
initialData: [],
builder: (BuildContext context, AsyncSnapshot<List<User>> snapshot) {
final List<User> users = snapshot.data;
return buildList(users);
})
}
Widget buildList(List<User> users) {
return ListView.builder(
itemCount: users.length,
itemBuilder: (BuildContext context, int index) {
final User user = users[index];
return ListTile(
title: Text('${user.firstName}'),
trailing: buildFavoriteButton(user));
});
}
Widget buildFavoriteButton(User user) {
User oldUser = user;
return StreamBuilder<User>(
stream: userBloc.outFavorite,
initialData: oldUser,
builder: (BuildContext context, AsyncSnapshot<User> snapshot) {
final User newUser = snapshot.data;
if (oldUser.id == newUser.id) {
oldUser = newUser;
}
return IconButton(
icon: Icon(Icons.favorite, color: oldUser.isFavorite ? Colors.red : Colors.blueGrey),
onPressed: () {
print('onPressed: This is called once');
userBloc.inFavorite.add(newUser);
});
});
}
外部流被调用一次,并且onPressed方法也被调用一次(如预期的那样)。
但是我遇到的问题是,当我按下Icon时:userBloc会打印N次(其中N是列表中的行数),就像我会连续按下Icon一样。
所以日志是:
class UserBloc {
final Repository _repository = Repository();
// More variables like the BehaviourSubject for outList and so on ...
final BehaviorSubject<User> _userFavoriteSubject = BehaviorSubject<User>();
Stream<User> _outFavorite = Stream.empty();
Stream<User> get outFavorite => _outFavorite;
Sink<User> get inFavorite => _userFavoriteSubject;
UserBloc() {
_outFavorite = _userFavoriteSubject.switchMap<User>((user) {
print('userBloc: This is called N times')
return user.isFavorite ? _repository.removeFromFavorite(user) : _repository.saveAsFavorite(user);
});
}
}
在这种情况下,操作(按图标)执行一次,但是userBloc获得N次输入。
为什么会这样,我该如何解决这个问题?
谢谢!
答案 0 :(得分:0)
我在定义的地方进行了测试:
Widget buildBody() {
return Column(
children: <Widget>[
StreamBuilder<int>(
stream: userBloc.outState,
initialData: 0,
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
print("Builder 1");
print("Snapshot 1: " + snapshot.data.toString());
return (IconButton(
icon: Icon(Icons.favorite, color: Colors.red),
onPressed: () {
print("onPressed 1");
userBloc.inEvents.add(1);
}));
},
),
StreamBuilder<int>(
stream: userBloc.outState,
initialData: 0,
builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
print("Builder 2");
print("Snapshot 2: " + snapshot.data.toString());
return (IconButton(
icon: Icon(Icons.favorite, color: Colors.red),
onPressed: () {
print("onPressed 2");
userBloc.inEvents.add(2);
}));
},
)
],
);
流:
_outState = _userSubject.switchMap<int>(
(integer) {
print("Input (sink): " + integer.toString());
return doSomething(integer);
},
);
当我运行此代码并单击IconButton 1时,输出为:
I/flutter ( 3912): Builder 1
I/flutter ( 3912): Snapshot 1: 0
I/flutter ( 3912): Builder 2
I/flutter ( 3912): Snapshot 2: 0
I/flutter ( 3912): onPressed 1
I/flutter ( 3912): Input (sink): 1
I/flutter ( 3912): Input (sink): 1
I/flutter ( 3912): Builder 1
I/flutter ( 3912): Snapshot 1: 1
I/flutter ( 3912): Builder 2
I/flutter ( 3912): Snapshot 2: 1
如您所见,打印“输入(接收器):1”显示了两次。 因此,对于接收器的任何输入,主题内的代码将执行n次,具体取决于订阅流的StreamBuilders的数量。
这种行为还好吗,还是一个错误?
我知道应该两次调用builder函数,因为流中的任何更改都将转发给所有订阅的StreamBuilder,但是主题内的代码也应该被调用两次?