从 v7.2.1 迁移到 flutter_bloc v 8.0.0 后不会触发 flutter_bloc 事件
Posted
技术标签:
【中文标题】从 v7.2.1 迁移到 flutter_bloc v 8.0.0 后不会触发 flutter_bloc 事件【英文标题】:flutter_bloc event is not trigger after Migrate to flutter_bloc v 8.0.0 from v7.2.1 【发布时间】:2021-12-31 09:34:26 【问题描述】:我尝试迁移 flutter_bloc v 8.0.0。阅读文档后,我知道我需要将 mapEventToState 迁移到 on。之后我没有收到错误但 _getMonks 事件没有触发。这是我的代码。有什么我错过的吗?
class MonkBloc extends Bloc<MonkEvent, MonkState>
final MonkRespository monkRespository;
late List<Monk> monks;
MonkBloc(required this.monkRespository) : super(MonkInitial())
on<GetMonksEvent>((event, emit) => _getMonks);
on<MonkSearchEvent>((event, emit) => _searchMonks);
Stream<MonkState> _getMonks(Emitter<MonkState> emit) async*
emit(MonkLoading());
try
final List<Monk> monks = await monkRespository.fetchMonks();
emit(MonkLoaded(monks: monks));
catch (e)
emit (MonkError(error: (e.toString())));
Stream<MonkState> _searchMonks(String query, Emitter<MonkState> emit) async*
emit(MonkLoading());
try
final List<Monk> monks = await monkRespository.searchMonks(query);
emit(MonkLoaded(monks: monks));
catch (e)
emit(MonkError(error: (e.toString())));
class MonkScreen extends StatefulWidget
static const routeName = '/monk';
final String? title;
final MonkScreenMode? screenMode;
const MonkScreen(Key? key, this.title, this.screenMode) : super(key: key);
@override
State<MonkScreen> createState() => _MonkScreenState();
class _MonkScreenState extends State<MonkScreen>
_loadMonks() async
BlocProvider.of<MonkBloc>(context).add(const GetMonksEvent());
@override
void initState()
super.initState();
_loadMonks();
@override
Widget build(BuildContext context)
return BaseWidget(
child: Scaffold(
backgroundColor: Theme.of(context).backgroundColor,
appBar: AppBar(
centerTitle: true,
backgroundColor: Theme.of(context).backgroundColor,
elevation: 0,
title: AutoSizeText(
widget.title!,
style: Theme.of(context).appBarTheme.titleTextStyle,
),
leading: IconButton(
onPressed: ()
Navigator.pop(context);
,
icon: Icon(
Icons.arrow_back,
color: Theme.of(context).primaryIconTheme.color!,
),
),
actions: [
IconButton(
onPressed: ()
showSearch(
context: context,
delegate: MonkSearch(screenMode: widget.screenMode!));
,
icon: Icon(
Icons.search,
color: Theme.of(context).primaryIconTheme.color!,
),
),
],
),
body: BlocBuilder<MonkBloc, MonkState>(
builder: (BuildContext context, MonkState monkState)
if (monkState is MonkError)
return const SomethingWentWrongScreen();
else if (monkState is MonkLoaded)
return listViewBuilder(
context, monkState.monks, widget.screenMode!);
return const Center(
child: CircularProgressIndicator(),
);
,
),
),
);
【问题讨论】:
【参考方案1】:这就是我迁移代码的方式。以防有人需要。
class MonkBloc extends Bloc<MonkEvent, MonkState>
final MonkRespository monkRespository;
late List<Monk> monks;
MonkBloc(required this.monkRespository) : super(MonkInitial())
on<GetMonksEvent>((event, emit) async
await _getMonks(emit);
);
on<MonkSearchEvent>((event, emit) async
await _searchMonks(event.query, emit);
);
Future<void> _getMonks(Emitter<MonkState> emit) async
emit(MonkLoading());
try
final List<Monk> monks = await monkRespository.fetchMonks();
emit(MonkLoaded(monks: monks));
catch (e)
emit (MonkError(error: (e.toString())));
Future<void> _searchMonks(String query, Emitter<MonkState> emit) async
emit(MonkLoading());
try
final List<Monk> monks = await monkRespository.searchMonks(query);
emit(MonkLoaded(monks: monks));
catch (e)
emit(MonkError(error: (e.toString())));
【讨论】:
【参考方案2】:class APIBloc extends Bloc<APIEvents, APIState>
//
final APIRepo apiRepo;
APIBloc(required this.apiRepo) : super(APIInitState())
on<APIEvents>(_addToValue);
Future<void> _addToValue(APIEvents event, Emitter<APIState> emit) async
print("onEvent");
emit(APILoading());
emit.forEach(
Stream.fromFuture(_callAPI(event).catchError((onError)
return onError;
)), onData: (value)
if (value is Response)
return APILoaded(response: value as Response);
else
return value as APIListError;
);
Future<Object> _callAPI(APIEvents event) async
try
if (event is FetchDashBoard)
return await apiRepo.getDashboardData(event.requestParams);
else if (event is DoLogin)
return await apiRepo.doLogin(event.requestParams);
else
throw (APIListError(
error: NoInternetException('No Internet'),
));
on SocketException
throw (APIListError(
error: NoInternetException('No Internet'),
));
on HttpException
throw (APIListError(
error: NoServiceFoundException('No Service Found'),
));
on FormatException
throw (APIListError(
error: InvalidFormatException('Invalid Response format'),
));
catch (e)
throw (APIListError(
error: UnknownException('Unknown Error'),
));
如果需要更多澄清代码,请关注以下站点。 https://flutterlearneasyway.blogspot.com/2021/11/flutter-bloc-pattern-800-call-api.html
【讨论】:
【参考方案3】:这里有错别字。
on<GetMonksEvent>((event, emit) => _getMonks);
您必须使用 args 调用 _getMonks 或仅传递事件侦听器本身:
用这个
on<GetMonksEvent>((event, emit) => _getMonks(event, emit));
或者更好的
on<GetMonksEvent>(_getMonks);
【讨论】:
以上是关于从 v7.2.1 迁移到 flutter_bloc v 8.0.0 后不会触发 flutter_bloc 事件的主要内容,如果未能解决你的问题,请参考以下文章
Flutter_bloc 从没有 UI 事件的 firestore 获取更新的数据