所以,我尝试学习 flutter,尤其是 BLoC 方法,并用 BLoC 制作了一个简单的 ToggleButtons。看起来像这样
切换UI.dart
class Flutter501 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter 50 With Bloc Package',
home: Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
BlocProvider<ToggleBloc>(
builder: (context) => ToggleBloc(maxToggles: 4),
child: MyToggle(),
)
],
),
),
),
);
}
}
class MyToggle extends StatelessWidget {
const MyToggle({
Key key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
ToggleBloc bloc = BlocProvider.of<ToggleBloc>(context);
return BlocBuilder<ToggleBloc, List<bool>>(
bloc: bloc,
builder: (context, state) {
return ToggleButtons(
children: [
Icon(Icons.arrow_back),
Icon(Icons.arrow_upward),
Icon(Icons.arrow_forward),
Icon(Icons.arrow_downward),
],
onPressed: (idx) {
bloc.dispatch(ToggleTap(index: idx));
},
isSelected: state,
);
},
);
}
}
ToogleBloc.dart
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/cupertino.dart';
abstract class ToggleEvent extends Equatable {
const ToggleEvent();
}
class ToggleTap extends ToggleEvent {
final int index;
ToggleTap({this.index});
@override
// TODO: implement props
List<Object> get props => [];
}
class ToggleBloc extends Bloc<ToggleEvent, List<bool>> {
final List<bool> toggles = [];
ToggleBloc({
@required int maxToggles,
}) {
for (int i = 0; i < maxToggles; i++) {
this.toggles.add(false);
}
}
@override
// TODO: implement initialState
List<bool> get initialState => this.toggles;
@override
Stream<List<bool>> mapEventToState(ToggleEvent event) async* {
// TODO: implement mapEventToState
if (event is ToggleTap) {
this.toggles[event.index] = !this.toggles[event.index];
}
yield this.toggles;
}
}
当我尝试点击/按下其中一个按钮时出现问题,但它不想更改为事件按钮。但每当我尝试按“热重载”时它就会起作用。就像每当按下按钮时我都必须进行 setState。
最佳答案
BlocBuilder.builder
仅当 State
时才执行方法变化。所以在你的情况下 State
是 List<bool>
您只需更改其中的特定索引并生成相同的对象。因此,BlocBuilder 无法确定列表是否发生更改,因此不会触发 UI 的重建。
参见https://github.com/felangel/bloc/blob/master/docs/faqs.md有关 flutter_bloc
中的解释文档:
Equatable properties should always be copied rather than modified. If an Equatable class contains a List or Map as properties, be sure to use List.from or Map.from respectively to ensure that equality is evaluated based on the values of the properties rather than the reference.
解决方案
在您的 ToggleBloc
中,像这样更改 List,因此它创建了一个全新的 List 对象:
@override
Stream<List<bool>> mapEventToState(ToggleEvent event) async* {
// TODO: implement mapEventToState
if (event is ToggleTap) {
this.toggles[event.index] = !this.toggles[event.index];
this.toggles = List.from(this.toggles);
}
yield this.toggles;
}
此外,请确保设置 props
对于您的事件,尽管对于这个具体问题来说并不重要。
关于Flutter BLoC 无法更新我的 bool 值列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65379743/