使用 API 实现 bloc 模式导致异常 "type 'Future<dynamic>' is not a subtype of type 'Widget?'"
implementing bloc pattern with API cause an exception "type 'Future<dynamic>' is not a subtype of type 'Widget?'"
我正在尝试实现 bloc 模式,我在其中使用存储库 class,其中包含使用 API 进行调用的所有方法。另一方面,我正在实施 BlocBuilder 以根据 bloc 状态呈现视图,但是我收到此错误 BlocBuilder(dirty, dependencies: [_LocalizationsScope-[GlobalKey#df8d0]], state: _BlocBuilderBaseState#dba40):
类型 'Future' 不是类型 'Widget?'
的子类型
我真的不确定问题出在哪里。这是一些代码片段。
这是导致错误的块class
class VehiclesBloc extends Bloc<VehiclesEvent,VehiclesState>{
VehiclesBloc(VehiclesState initialState) : super(initialState);
@override
Stream<VehiclesState> mapEventToState(VehiclesEvent event) async* {
// TODO: implement mapEventToState
if(event is LoadVehiclesList){
yield* mapLoadEventToState(event);
}
}
Stream<VehiclesState> mapLoadEventToState(LoadVehiclesList event) async* {
if(event is LoadVehiclesList){
var response = await VehiclesService().getAll();
if(response.IsSuccess){
yield VehiclesLoaded(response.Data);
}else{
yield VehiclesLoadingFailed(response.ErrorList.toString());
}
}else{
yield VehiclesLoading();
}
}
}
这是实现 Bloc Builder 的 Statefull 小部件
class VehicleList extends StatefulWidget {
const VehicleList({Key key}) : super(key: key);
static const String routeName = "/VehicleList";
//final ScrollController scrollController;
@override
_VehicleListState createState() => _VehicleListState();
}
class _VehicleListState extends State<VehicleList> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
VehiclesBloc vehiclesBloc =
VehiclesBloc(VehiclesLoading())..add(LoadVehiclesList());
@override
void initState() {
// TODO: implement initState
super.initState();
//VehiclesService().getAll();
}
@override
void dispose() {
// TODO: implement dispose
vehiclesBloc.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
final isRtl = context.locale.languageCode == "ar";
return Scaffold(
key: _scaffoldKey,
backgroundColor: kBackgroundColor,
drawer: SideNavigationDrawer(),
body: Container(
child: Column(
children: [
SizedBox(
height: 15,
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
IconButton(
onPressed: () {
_scaffoldKey.currentState.openDrawer();
},
icon: Icon(
Icons.menu,
size: 35,
color: Colors.black,
),
)
],
),
Expanded(
child: SingleChildScrollView(
child: Column(
children: [
BlocBuilder<VehiclesBloc,VehiclesState>(
builder: (context, state) {
if (state is VehiclesLoaded) {
// return BuildListVehicle(state.lsVehicle);
return Center();
} else if (state is VehiclesLoadingFailed) {
return Center(
child: CustomErrorWidget(),
);
} else {
return Center(
child: LoadingDialog.showLoadingDialog(context,
text: ""),
);
}
},
cubit: vehiclesBloc,
),
],
),
),
)
],
),
));
}
我认为这个代码部分导致了问题:
return Center(
child: LoadingDialog.showLoadingDialog(context,text: ""),
);
可能,LoadingDialog.showLoadingDialog
不是 return 小部件,而只是 return 未来的一个功能。
对于副作用(例如,您想显示对话框),您应该使用侦听器而不是在构建方法中执行此类代码。而不是 BlocBuilder
,只需使用 BlocConsumer
并添加侦听器:
BlocConsumer<VehiclesBloc,VehiclesState>(
listener: (context, state) {
if (state is {your loading state}) {
LoadingDialog.showLoadingDialog(context, text: "");
}
},
builder: ...,
),
关于您的代码的更多见解:
- 不要将 BLoC 创建为有状态小部件中的变量,而是使用 BlocProvider 来处理 BLoC 的 create/dispose 部分。
- 在加载数据之前产生
VehiclesLoading
状态,而不仅仅是作为“其他”情况。这样您就可以在 UI 中轻松处理加载行为。
要解决上述问题,只需按照文档:https://bloclibrary.dev/
我正在尝试实现 bloc 模式,我在其中使用存储库 class,其中包含使用 API 进行调用的所有方法。另一方面,我正在实施 BlocBuilder 以根据 bloc 状态呈现视图,但是我收到此错误 BlocBuilder
我真的不确定问题出在哪里。这是一些代码片段。
这是导致错误的块class
class VehiclesBloc extends Bloc<VehiclesEvent,VehiclesState>{
VehiclesBloc(VehiclesState initialState) : super(initialState);
@override
Stream<VehiclesState> mapEventToState(VehiclesEvent event) async* {
// TODO: implement mapEventToState
if(event is LoadVehiclesList){
yield* mapLoadEventToState(event);
}
}
Stream<VehiclesState> mapLoadEventToState(LoadVehiclesList event) async* {
if(event is LoadVehiclesList){
var response = await VehiclesService().getAll();
if(response.IsSuccess){
yield VehiclesLoaded(response.Data);
}else{
yield VehiclesLoadingFailed(response.ErrorList.toString());
}
}else{
yield VehiclesLoading();
}
}
}
这是实现 Bloc Builder 的 Statefull 小部件
class VehicleList extends StatefulWidget {
const VehicleList({Key key}) : super(key: key);
static const String routeName = "/VehicleList";
//final ScrollController scrollController;
@override
_VehicleListState createState() => _VehicleListState();
}
class _VehicleListState extends State<VehicleList> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
VehiclesBloc vehiclesBloc =
VehiclesBloc(VehiclesLoading())..add(LoadVehiclesList());
@override
void initState() {
// TODO: implement initState
super.initState();
//VehiclesService().getAll();
}
@override
void dispose() {
// TODO: implement dispose
vehiclesBloc.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
final isRtl = context.locale.languageCode == "ar";
return Scaffold(
key: _scaffoldKey,
backgroundColor: kBackgroundColor,
drawer: SideNavigationDrawer(),
body: Container(
child: Column(
children: [
SizedBox(
height: 15,
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
IconButton(
onPressed: () {
_scaffoldKey.currentState.openDrawer();
},
icon: Icon(
Icons.menu,
size: 35,
color: Colors.black,
),
)
],
),
Expanded(
child: SingleChildScrollView(
child: Column(
children: [
BlocBuilder<VehiclesBloc,VehiclesState>(
builder: (context, state) {
if (state is VehiclesLoaded) {
// return BuildListVehicle(state.lsVehicle);
return Center();
} else if (state is VehiclesLoadingFailed) {
return Center(
child: CustomErrorWidget(),
);
} else {
return Center(
child: LoadingDialog.showLoadingDialog(context,
text: ""),
);
}
},
cubit: vehiclesBloc,
),
],
),
),
)
],
),
));
}
我认为这个代码部分导致了问题:
return Center(
child: LoadingDialog.showLoadingDialog(context,text: ""),
);
可能,LoadingDialog.showLoadingDialog
不是 return 小部件,而只是 return 未来的一个功能。
对于副作用(例如,您想显示对话框),您应该使用侦听器而不是在构建方法中执行此类代码。而不是 BlocBuilder
,只需使用 BlocConsumer
并添加侦听器:
BlocConsumer<VehiclesBloc,VehiclesState>(
listener: (context, state) {
if (state is {your loading state}) {
LoadingDialog.showLoadingDialog(context, text: "");
}
},
builder: ...,
),
关于您的代码的更多见解:
- 不要将 BLoC 创建为有状态小部件中的变量,而是使用 BlocProvider 来处理 BLoC 的 create/dispose 部分。
- 在加载数据之前产生
VehiclesLoading
状态,而不仅仅是作为“其他”情况。这样您就可以在 UI 中轻松处理加载行为。 要解决上述问题,只需按照文档:https://bloclibrary.dev/