How do I trigger bloc event from addListener?
After researching for some days, I found that we have to specify BuildContext rather than make it dynamic. As during runtime this field will check the type, but will not check during compilation time. This was the issue that couldn't generate a read function and trigger the bloc event during compilation time when the setupScrollController function was called.
Before
After
Reference: https://blog.csdn.net/Mr_Tony/article/details/111738933
Prajun Lungeli
Updated on January 02, 2023Comments
-
Prajun Lungeli over 1 year
I'm trying to fetch data when I reach the last item scrolling the list view, but the event isn't triggering. As soon as I end up with the last item, the scrollController is used for listening to the scrolling activity and should trigger the bloc event to fetch more data but it isn't happening.
Here is the code for that part:
class OrderHistoryPage extends StatelessWidget { const OrderHistoryPage({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return BlocProvider( create: (context) => getIt<OrderHistoryWatcherBloc>() ..add(const OrderHistoryWatcherEvent.fetchOrderHistory()), child: PageBuilder(), ); } } class PageBuilder extends StatelessWidget { final scrollController = ScrollController(); PageBuilder({Key? key}) : super(key: key); @override Widget build(BuildContext context) { return BlocBuilder<OrderHistoryWatcherBloc, OrderHistoryWatcherState>( builder: (context, state) { if (state.isProcessing) { return const Scaffold( body: CustomLoadingIndicator(), ); } else { return state.failureOrSuccess?.fold( (l) => Scaffold( body: FailedContainer( onTap: () => context.read<OrderHistoryWatcherBloc>().add( const OrderHistoryWatcherEvent .fetchOrderHistory(), ), ), ), (r) { setupScrollController(context, r.next); var ordersList = r.results; if (state.searchKey != null) { ordersList = ordersList .where((element) => element.id .toString() .toLowerCase() .contains(state.searchKey!.toLowerCase())) .toList(); } return MainScaffold( requiredAppBar: true, pageName: pageName, requiredAppDrawer: true, body: Column( children: [ CustomSearchBox( icon: Icons.search_sharp, hintText: 'Search Orders by Id', onChanged: (v) { context .read<OrderHistoryWatcherBloc>() .add(OrderHistoryWatcherEvent.searchKey(v)); }, ), sizedBoxedSmall, Expanded( child: RefreshIndicator( onRefresh: () async { context.read<OrderHistoryWatcherBloc>().add( const OrderHistoryWatcherEvent .fetchOrderHistory()); }, child: ordersList.isNotEmpty ? ListView.builder( physics: const AlwaysScrollableScrollPhysics(), controller: scrollController, itemBuilder: (context, index) { if (index < ordersList.length) { return OrderListTile( orderId: ordersList[index].id, createdDateTime: ordersList[index].created, totalPrice: ordersList[index].total, orderStatus: ordersList[index].status); } else { Timer(const Duration(milliseconds: 30), () { scrollController.jumpTo(scrollController .position.maxScrollExtent); }); return const Center( child: CircularProgressIndicator()); } }, itemCount: ordersList.length + (state.isLoading ? 1 : 0), ) : const Text('Search result not found'), ), ), ], ), ); }) ?? Container(); } }); } void setupScrollController(context, String? url) { scrollController.addListener(() { if (scrollController.position.atEdge) { if (scrollController.position.pixels != 0) { debugPrint('from order history page : $url'); context .read<OrderHistoryWatcherBloc>() .add(OrderHistoryWatcherEvent.fetchOrderHistory(url: url)); } } }); } }
Here is the error log:
══╡ EXCEPTION CAUGHT BY FOUNDATION LIBRARY ╞════════════════════════════════════════════════════════ The following NoSuchMethodError was thrown while dispatching notifications for ScrollController: Class 'StatefulElement' has no instance method 'read'. Receiver: Instance of 'StatefulElement' Tried calling: read()
When the exception was thrown, this was the stack: #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:63:5) #1 PageBuilder.setupScrollController. (package:mitho_food_vendor/features/order/presentation/pages/order_history_page.dart:130:16) #2 ChangeNotifier.notifyListeners (package:flutter/src/foundation/change_notifier.dart:308:24) #3 ChangeNotifier.notifyListeners (package:flutter/src/foundation/change_notifier.dart:308:24) #4 ScrollPosition.notifyListeners (package:flutter/src/widgets/scroll_position.dart:968:11) #5 ScrollPosition.forcePixels (package:flutter/src/widgets/scroll_position.dart:380:5) #6 ScrollPositionWithSingleContext.jumpTo (package:flutter/src/widgets/scroll_position_with_single_context.dart:198:7)
#7 ScrollController.jumpTo (package:flutter/src/widgets/scroll_controller.dart:173:16) #8 PageBuilder.build.... (package:mitho_food_vendor/features/order/presentation/pages/order_history_page.dart:101:56) (elided 11 frames from class _RawReceivePortImpl, class _Timer, dart:async, and dart:async-patch)The ScrollController sending notification was: ScrollController#0c24c(one client, offset 34.4)
-
Brian Formento over 2 yearsI would recommend not using images as code snippets, if you can, try to write the code yourself, apart from being cleaner, it helps people who search by code :)
-
Prajun Lungeli over 2 yearsThanks, Brian Formento for the suggestion, I'll make sure to write the code next time.