Flutter bloc state is not emitting or updating. Method mapEventToState is never called - flutter

The following code was working before null safety with flutter_bloc 4.0.1 but after null safety migration the state is not updating / emitting / broadcasting as expected with flutter_bloc 7.3.3.
The below _reactToState and mapEventToState methods are never called. How can I fix it?
Splash Screen
class SplashScreen extends StatefulWidget {
final Strapper strapper;
final Service? service;
SplashScreen(this.strapper, this.service);
#override
State<StatefulWidget> createState() => _SplashScreenState();
}
class _SplashScreenState extends State<SplashScreen> {
SplashBloc? _splashBloc;
#override
void didChangeDependencies() {
super.didChangeDependencies();
if (_splashBloc == null) {
_splashBloc = SplashBloc(widget.strapper, widget.service);
_splashBloc!.stream.listen(_reactToState);
}
}
#override
dispose() {
_splashBloc?.close();
_splashBloc = null;
super.dispose();
}
#override
Widget build(BuildContext context) {
return BlocProvider<SplashBloc>(
create: (context) => _splashBloc!,
child: BlocBuilder<SplashBloc, SplashBlocState>(
builder: (context, state) => Container(
child: Stack(
children: <Widget>[
LogoPanel(
_showWidgetForState(state),
),
],
),
),
),
);
}
void _reactToState(SplashBlocState state) {
if (state is InitializingSplashBlocState) {
if (widget.logOut) {
_splashBloc!.add(LogoutSplashBlocEvent());
} else {
_splashBloc!.add(CInitializationSplashBlocEvent());
}
} else if (state is AuthSuccessSplashBlocState) {
App.navigateToSomewhere(context, state.isNewUser);
}
}
Widget _showWidgetForState(SplashBlocState state) {
if (state is InitializingSplashBlocState) {
return _getProgressIndicator();
} else if (state is ChooseSomethingSplashBlockState ) {
return _showSignInWidget();
}
}
}
Splash Bloc
class SplashBloc extends Bloc<SplashBlocEvent, SplashBlocState> {
final Strapper? strapper;
final Service? service;
SplashBloc(this.strapper, this.service) : super(InitializingSplashBlocState());
#override
Stream<SplashBlocState> mapEventToState(event) async* {
if (event is CInitializationSplashBlocEvent) {
await strapper!.run();
}
bool chooseSomething = !service!.hasSomeSelection;
if (chooseSomething) {
yield ChooseSomethingSplashBlockState();
} else if (event is RAuthSplashBlocEvent) {
yield AuthSplashBlocState();
var authState = await _run();
yield authState;
}
}
Future<SplashBlocState> _run() async {
// Do something
}
}
Splash Bloc Event
abstract class SplashBlocEvent extends Equatable {
const SplashBlocEvent();
#override
List<Object> get props => [];
}
class CInitializationSplashBlocEvent extends SplashBlocEvent {}
class RAuthSplashBlocEvent extends SplashBlocEvent {}
Splash Bloc State
abstract class SplashBlocState extends Equatable {
const SplashBlocState();
#override
List<Object> get props => [];
}
class InitializingSplashBlocState extends SplashBlocState {}
class AuthSplashBlocState extends SplashBlocState {}
class ChooseSomethingSplashBlockState extends SplashBlocState {}
class AuthSuccessSplashBlocState extends SplashBlocState {
final CurrentUser? user;
final bool isNewUser;
AuthSuccessSplashBlocState(this.user, this.isNewUser);
}

As per the documentation:
In v6.0.0, the above snippet does not output the initial state and only outputs subsequent state changes. The previous behavior can be achieved with the following:
final bloc = MyBloc();
print(bloc.state);
bloc.listen(print);
So I changed my code in the Splash screen as following:
#override
void didChangeDependencies() {
super.didChangeDependencies();
if (_splashBloc == null) {
_splashBloc = SplashBloc(widget.strapper, widget.service);
_reactToState(_splashBloc!.state); // Added this line
_splashBloc!.stream.listen(_reactToState);
}
}
And that's it. It worked!
_reactToState and mapEventToState are definitely being called.

when you use Streamcontrollers it greatly simplifies state. I build a bloc code to manage state. The materialapp child is the splashWidget whose job is to render the hour, minute, second from bloc code emitting Time state. If the user clicks the splash screen or 5 seconds elapses the splash screen will be replaced with the HomePageWidget. bloc code controls the starting and stopping of the timer using an timerState event.
'package:flutter/material.dart';
import 'bloc_splash.dart';
import 'main.dart';
class SplashWidget extends StatelessWidget {
const SplashWidget({Key? key}) : super(key: key);
_redirectToHome(BuildContext context)
{
Navigator.pushReplacement(context,MaterialPageRoute(builder:(_)=>MyHomePage(title:"helloWorld")));
}
String _displayClock(Time ? data)
{
String retVal="";
if (data!=null)
{
retVal="Time: ${data.hour} : ${data.minute} : ${data.second}";
}
return retVal;
}
#override
Widget build(BuildContext context) {
SplashBloc _bloc=SplashBloc();
_bloc.timerOnChange(StartTimer());
return Scaffold(
body:InkWell(
onTap: (){_bloc.timerOnChange(StopTimer());
_redirectToHome(context);
},
child:Container(
child:
StreamBuilder<TimeState>(
stream:_bloc.timeStream,
builder:(context,snapshot)
{
if(snapshot.hasData && (snapshot.data is RedirectState))
{
return MyHomePage(title:"helloWorld");
}
return Center(child:Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("Splash Screen", style:TextStyle(fontSize: 24,fontWeight: FontWeight.bold)),
Text(_displayClock(snapshot.data?.time)),
]));
}
)
))
);
}
}
bloc code
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.dart';
import 'dart:ui';
import 'dart:async';
abstract class TimerEvent extends Equatable{
const TimerEvent();
#override
List<Object>get props=>[];
}
class StartTimer extends TimerEvent{
const StartTimer();
}
class StopTimer extends TimerEvent{
const StopTimer();
}
class Time{
final int hour;
final int minute;
final int second;
Time(this.hour,this.minute,this.second);
}
class TimeState extends Equatable{
final Time time;
TimeState(this.time);
#override
List<Object> get props=>[time];
}
class RedirectState implements TimeState{
final Time time;
RedirectState(this.time);
#override
List<Object> get props=>[time];
#override
// TODO: implement stringify
bool? get stringify => throw UnimplementedError();
}
class TimerState extends Equatable{
final bool started;
const TimerState(this.started);
#override
List<Object> get props => [started];
}
class SplashBloc
{
SplashBloc();
Timer ?_timer;
var countDown=5;
Stream<TimeState> get timeStream=> _timeController.stream;
final _timeController =BehaviorSubject<TimeState>();
void dispose()
{
_timeController.close();
}
void _pushTimeOnTheStream(Timer timer)
{
DateTime now=DateTime.now();
_timeController.sink.add(TimeState(Time(now.hour,now.minute,now.second)));
this.countDown-=1;
if (this.countDown==0)
{
timerOnChange(StopTimer());
_timeController.sink.add(RedirectState(Time(0,0,0)));
}
}
void timerOnChange(TimerEvent event) {
if (event is StartTimer)
{
_timer=Timer.periodic(Duration(seconds: 1),_pushTimeOnTheStream);
}
else if(event is StopTimer){
//_timerController.sink.add(TimerState(false));
_timer?.cancel();
}
}
}
app
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const SplashWidget(),
);
}
}

Related

Getx Flutter dependency injection through binding

I am trying to use binding class to inject dependecies into my flutters application but for some reason its not working as i expected
binding class
class LibraryHomeBinding extends Bindings {
#override
void dependencies() {
Get.put(LibraryHomeController(), tag: 'home');
}
}
controller class
class LibraryHomeController extends GetxController {
#override
void onInit() {
print('initilizing');
super.onInit();
}
#override
void onReady() {
print('Controller ready');
super.onReady();
}
#override
void onClose() {
print('Controller closing');
super.onClose();
}
}
home
class LibraryHome extends StatelessWidget {
LibraryHome({super.key, required this.title});
final String title;
final libraryHomeBinding = Get.find(tag: 'home');
...
}
main
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return GetMaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: lightTheme,
getPages: [
GetPage(
name: '/home',
page: () => LibraryHome(title: 'Library'),
binding: LibraryHomeBinding(),
)
],
initialRoute: '/home',
);
}
}
i am getting this error
""dynamic" not found. You need to call "Get.put(dynamic())" or "Get.lazyPut(()=>dynamic())""
on the binding class i think using extends is not quite right but use instead with/implements
class LibraryHomeBinding with Bindings {
#override
void dependencies() {
/// use lazy put
Get.lazyPut(LibraryHomeController(),fenix: true,tag: 'home');
}
}
then on the controller do it like this
class LibraryHomeController extends GetxController {
final findBind = Get.find<LibraryHomeController>( tag: "home");
#override
void onInit() {
print('initilizing');
super.onInit();
}
}
when calling the Get.find() you specified the tag, but you didn't specify the type, Getx use the type and tag to generate a consistent key to get what you want so you need to do this :
final libraryHomeBinding = Get.find<LibraryHomeController>(tag: 'home');
or
final LibraryHomeController libraryHomeBinding = Get.find(tag: 'home');
now it will find it.

Async Redux: How to use Events as one-to-many

This is a case.
I want to use one TimerWidget for 1+ forms.
And i don`t want to save its state in the Store.
So I created it as an Event, and realized like this.
/// Action
class TimeIsOnAction extends AppAction {
TimeIsOnAction(this.timerCounter);
final int timerCounter;
#override
Future<AppState?> reduce() async {
return state.copyWith(timerCounter: Event(timerCounter));
}
}
/// Widget
class TimerWidget extends StatelessWidget {
const TimerWidget({Key? key, required this.timerCounter}) : super(key: key);
final Event<int> timerCounter;
#override
Widget build(BuildContext context) {
final timer = timerCounter.state ?? 0;
// !!!! Consume or Not ???
timerCounter.consume();
return Center(child: Text('$timer'));
}
}
//////////////////////////////////////////////////////////////////////////////
/// Connector
class TimerWidgetConnector extends StatelessWidget {
const TimerWidgetConnector({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return StoreConnector<AppState, _Vm>(
vm: () => _Factory(),
builder: (context, vm) {
return TimerWidget(
timerCounter: vm.timerCounter,
);
},
);
}
}
///
class _Factory extends AppVmFactory {
#override
_Vm fromStore() {
return _Vm(
timerCounter: state.timerCounter,
);
}
}
///
class _Vm extends Vm {
final Event<int> timerCounter;
_Vm({
required this.timerCounter,
}) : super(equals: [timerCounter]);
}
/// Persisting
#override
Future<void> persistDifference(
{AppState? lastPersistedState, required AppState newState}) async {
if (lastPersistedState == null || lastPersistedState != newState) {
return _safeWrapperS(() async {
final json = newState.toJson();
final s = jsonEncode(json);
_saveString(_appStateKey, s);
return;
});
}
}
/// Applying 1
children: [
const Center(child: TimerWidgetConnector()),
Center(child: Text('$isDarkMode')),
/// Applying 2
10.verticalSpace,
const Center(child: TimerWidgetConnector()),
10.verticalSpace,
But! If i consume event in TimerWidget.build after applying - it works only on one Form
If i don't consume - its state automatically persisted with every event changing.
Is there recipe for that case?

State is not yielded thus unable to change icon color

I'm working on a metronome app and having problem with the bloc states. I'm toggling the metronome on and off with a FAB button and expecting the FAB icon color to change upon toggling. Could you have a look at the code and direct me towards what I am doing wrong here?
/// EVENTS
abstract class MetronomeEvent extends Equatable {
const MetronomeEvent();
#override
List<Object> get props => [];
}
class InitMetronomeEvent extends MetronomeEvent {}
class DisposeMetronomeEvent extends MetronomeEvent {}
class ToggleOnOffMetronomeEvent extends MetronomeEvent {}
class IncreaseTempoMetronomeEvent extends MetronomeEvent {}
class DecreaseTempoMetronomeEvent extends MetronomeEvent {}
class ChangeTempoMetronomeEvent extends MetronomeEvent {
final int givenTempo;
const ChangeTempoMetronomeEvent({required this.givenTempo});
#override
List<Object> get props => [givenTempo];
#override
String toString() {
return 'ChangeTempoMetronomeEvent{givenTempo: $givenTempo}';
}
}
Here is the states:
/// STATES
abstract class MetronomeState extends Equatable {
const MetronomeState();
}
class MetronomeInitial extends MetronomeState {
#override
List<Object> get props => [];
}
class ToggleOnOffMetronomeState extends MetronomeState {
final bool isMetronomeOn;
const ToggleOnOffMetronomeState({required this.isMetronomeOn});
#override
List<Object?> get props => [isMetronomeOn];
}
And my bloc:
/// BLOC
class MetronomeBloc extends Bloc<MetronomeEvent, MetronomeState> {
final _metronome = getIt<MetronomeService>();
MetronomeBloc() : super(MetronomeInitial()) {
on<InitMetronomeEvent>((event, emit) {
_metronome.init();
});
on<DisposeMetronomeEvent>((event, emit) {
_metronome.dispose();
});
on<ToggleOnOffMetronomeEvent>((event, emit) {
_metronome.toggleOnOff();
emit(ToggleOnOffMetronomeState(isMetronomeOn: _metronome.isMetronomeOn));
debugPrint("TOGGLED METRONOME ${_metronome.isMetronomeOn ? "ON" : "OFF"}");
});
on<IncreaseTempoMetronomeEvent>((event, emit) {
_metronome.increaseTempo();
});
on<DecreaseTempoMetronomeEvent>((event, emit) {
_metronome.decreaseTempo();
});
on<ChangeTempoMetronomeEvent>((event, emit) {
_metronome.changeTempo(event.givenTempo);
});
}
}
And I'm using BlocBuilder to listen and rebuild the widget below:
FloatingActionButton(
onPressed: () {
_bloc.add(ToggleOnOffMetronomeEvent());
},
child: BlocBuilder<MetronomeBloc, MetronomeState>(
builder: (context, state) {
if (state is ToggleOnOffMetronomeState) {
_isMetronomeOn = state.isMetronomeOn;
}
return Icon(
Icons.power_settings_new,
color: _isMetronomeOn
? Colors.red
: Theme
.of(context)
.floatingActionButtonTheme
.backgroundColor,
);
},
),
)

Using a bloc with Navigator 2.0

Hi I am trying to use a bloc instead of ChangeNotifierDelegate in my RouterDelegate class. Unfortunately the bloc is not being called when a route is changed through my routebloc, not sure why. I have tried wrapping the delegate in a BlocProvider, but it made no difference (I currently have it injected above in the main file.)
runApp(MyApp());
class _MyApp AppState extends State<MyApp> {
MyAppRouterDelegate _routerDelegate = MyAppRouterDelegate();
MyAppRouteInformationParser _routeInformationParser = MyAppRouteInformationParser();
#override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider(
lazy: false,
create: (context) => getIt<AuthBloc>()//..add(AppStarted()),
),
BlocProvider(
lazy: false,
create: (context) => getIt<RouterBloc>(),
),
],
child: MaterialApp.router(
title: 'MyApp',
theme: globalAppThemeData,
routerDelegate: _routerDelegate,
routeInformationParser: _routeInformationParser,
),
);
}
}
In my RouterDelegate I have .....
lass MyAppRouterDelegate extends RouterDelegate<MyAppConfiguration>
with ChangeNotifier, PopNavigatorRouterDelegateMixin<MyAppConfiguration> {
final GlobalKey<NavigatorState> _navigatorKey;
String currentPage = '';
String selectedItem = '';
#override
GlobalKey<NavigatorState> get navigatorKey => _navigatorKey;
MyAppRouterDelegate() : _navigatorKey = GlobalKey<NavigatorState>();
#override
MyAppConfiguration get currentConfiguration {
currentPage = currentConfiguration.screen;
selectedItem = currentConfiguration.selectedItemId;
if (currentPage == UNKNOWN) {
return MyAppConfiguration.unknown();
} else if (currentPage == SPLASH) {
return MyAppConfiguration.splash();
} else if (currentPage == LOGIN) {
return MyAppConfiguration.login();
} else {
return MyAppConfiguration.unknown();
}
}
#override
Widget build(BuildContext context) {
List<Page> pages = [SplashPage(SPLASH)];
return BlocBuilder<RouterBloc, RouterState>(
builder: (context, state) {
if (state is ChangedRoute) {
pages.clear();
pages = state.pages;
}
return Navigator(
key: navigatorKey,
pages: pages,
onPopPage: (route, result) {
if (!route.didPop(result)) return false;
context.read<AuthBloc>().add(AuthEventLoggedOut());
return true;
},
);
},
);
}
#override
Future<void> setNewRoutePath(MyAppConfiguration configuration) async {
if (configuration.unknown) {
currentPage = UNKNOWN;
selectedItem = configuration.selectedItemId;
} else if (configuration.isSplashPage) {
currentPage = SPLASH;
selectedItem = configuration.selectedItemId;
} else if (configuration.isLoginPage) {
currentPage = LOGIN;
selectedItem = configuration.selectedItemId;
} else if (configuration.isSignUpPage)
currentPage = SIGNUP;
selectedItem = configuration.selectedItemId;
} else {
print(Constants.failureCouldNotSetRoute);
}
}
_clear() {
currentPage = UNKNOWN;
selectedItem = '';
}
}
In my app configuration...
class MyAppInformationParser
extends RouteInformationParser<MyAppConfiguration> {
#override
Future<MyAppConfiguration> parseRouteInformation(RouteInformation? routeInformation) async {
final uri = Uri.parse(routeInformation!.location!);
if (uri.pathSegments.length == 0) {
return MyAppConfiguration.splash();
} else if (uri.pathSegments.length == 1) {
final first = uri.pathSegments[1].toLowerCase();
if (first == LOGIN) {
return MyAppConfiguration.login();
} else {
return MyAppConfiguration.unknown();
}
} else {
return MyAppConfiguration.unknown();
}
}
#override
RouteInformation restoreRouteInformation(MyAppConfiguration configuration) {
if (configuration.isUnknownPage) {
return RouteInformation(location: '/unknown');
} else if (configuration.isSplashPage) {
return RouteInformation(location: '/splash');
} else if (configuration.isLoginPage) {
return RouteInformation(location: '/login');
} else {
return RouteInformation(location: '/unknown');
}
}
}
My auth bloc ...
#injectable
class AuthBloc extends Bloc<AuthEvent, AuthState> {
IAuthFacade authRepo;
RouterBloc routerBloc;
AuthBloc(this.authRepo, this.routerBloc) : super(Uninitialized());
#override
Stream<AuthState> mapEventToState(
AuthEvent event,
) async* {
if (event is AppStarted) {
yield AuthenticationLoading();
Option<CurrentUser> user = await authRepo.getSignedInUser();
yield user.fold(() {
routerBloc.add(RouterEventNewPage(pages: [LoginPage(LOGIN)]));
return Unauthenticated();
}, (user) {
routerBloc.add(RouterEventNewPage(pages: [HomePage(HOME)]));
return Authenticated(user);
});
}
if (event is AuthEventLoggedOut) {
authRepo.signOut();
///TODO: clear hive here??
}
}
}
abstract class AuthEvent extends Equatable {
#override
List<Object> get props => [];
}
//
class AppStarted extends AuthEvent {}
//
class AuthEventLoggedOut extends AuthEvent {}
abstract class AuthState extends Equatable {
#override
List<Object> get props => [];
}
//
class Uninitialized extends AuthState {}
//
class Authenticated extends AuthState {
final CurrentUser user;
Authenticated(this.user);
}
//
class Unauthenticated extends AuthState {}
//
class AuthenticationLoading extends AuthState {}
My Router Bloc...
#injectable
class RouterBloc extends Bloc<RouterEvent, RouterState> {
RouterBloc() : super(RouterInitial());
#override
Stream<RouterState> mapEventToState(
RouterEvent event,
) async* {
if (event is RouterEventNewPage) {
yield ChangingRoute();
yield ChangedRoute(pages: event.pages);
}
}
}
abstract class RouterEvent extends Equatable {
const RouterEvent();
#override
List<Object> get props => [];
}
class RouterEventNewPage extends RouterEvent {
final List<Page> pages;
RouterEventNewPage({required this.pages});
#override
List<Object> get props => [pages];
}
abstract class RouterState extends Equatable {
const RouterState();
#override
List<Object> get props => [];
}
class RouterInitial extends RouterState {}
class ChangingRoute extends RouterState {}
class ChangedRoute extends RouterState {
final List<Page> pages;
ChangedRoute({required this.pages});
#override
List<Object> get props => [pages];
}
The app runs through the Navigator in the build function of the delegate first, it navigates to the splash screen perfectly, then after my animation finishes in the splash screen it calls the auth bloc to check if user is authorised, this works perfectly which then calls the routerbloc. The router bloc adds the new login screen (as the user is logged out). However, the bloc inside the build function of the MyAppRouterDelegate is not firing again.
Any help provided would be very much appreciated.
When it runs through the MyAppRouterDelegates build function the first time I do receive the error
"
════════ Exception caught by scheduler library ═════════════════════════════════
The following StackOverflowError was thrown during a scheduler callback:
Stack Overflow
When the exception was thrown, this was the stack
#0 CrokettRouterDelegate.currentConfiguration
package:crokett/routes/crokett_router_delegate.dart:20
"
But I don't receive any more information on the error.
Don't you need a notifyListeners() somewhere in your blocBuilder after you update the page stack?
I am interested to know if you got it working.

Flutter Bloc How to update Widget in BlocBuilder from the Widget itself?

How can to update a Bloc widget from the bloc Widget itself with the Slider?
The Event for the Chart Data is executed from another Widget.
When the data is fetched this Widget is opened.
When I change the Slider I want the chart to be updated withe the date but keep the other data.
Would be too much to fetch all the Data again.
How can I get access only the data changed from the same widget?
I have the following Bloc Builder Widget, bloc_event, bloc and bloc_state
The Widget:
class ChartWidget extends StatelessWidget {
ChartWidget({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
double valueSliderDate;
return BlocBuilder<ChartDataBloc, ChartDataState>(
builder: (context, state) {
if (state is ChartDataLoadInProgress) {
return LoadingIndicator();
} else if (state is ChartDataLoadSuccess) {
final chartData = state.chartData;
final maxValueAll = getMaxValueAll(chartData);
final List<double> dates = getValuesDate(chartData);
valueSliderDate = dates.first;
return Column(children: <Widget>[
Expanded(
child: MyFancyChart(chartData, valueSliderDate),
),
Slider(
min: dates.first,
max: dates.last,
divisions: dates.length,
value: valueSliderDate,
onChanged: (value) {
context.read<ChartDataBloc>().add(DateSliderSet(value));
},
),
]);
} else {
return Container();
}
},
);
}
This is the bloc_event with two events:
abstract class ChartDataEvent {
const ChartDataEvent();
#override
List<Object> get props => []; }
class SpecificIndicatorIdSet extends ChartDataEvent {
const SpecificIndicatorIdSet(this.indicator);
final Indicator indicator;
#override
List<Object> get props => [indicator]; }
class DateSliderSet extends ChartDataEvent {
const DateSliderSet(this.dateSlider);
final double dateSlider;
#override
List<Object> get props => [dateSlider]; }
This is the bloc itself:
class ChartDataBloc extends Bloc<ChartDataEvent, ChartDataState> {
final ChartDataRepository chartDataRepository;
ChartDataBloc({#required this.chartDataRepository}) : super(ChartDataLoadInProgress());
#override
Stream<ChartDataState> mapEventToState(ChartDataEvent event) async* {
if (event is SpecificIndicatorIdSet) {
yield* _mapIndicatorsLoadedToState(event);
} else if (event is DateSliderSet) {
yield* _mapDateSliderToState(event); } }
Stream<ChartDataState> _mapDateSliderToState(
DateSliderSet event
) async* {
try {
final dateSlider = event.dateSlider;
yield DateSliderLoadSuccess(
dateSlider,
);
} catch (_) {
yield DateSliderLoadFailure(); } }
Stream<ChartDataState> _mapIndicatorsLoadedToState(
SpecificIndicatorIdSet event
) async* {
try {
final chartData = await this.chartDataRepository.loadChartData(event.indicator.id);
yield ChartDataLoadSuccess(
sortToListOfLists(chartData),
event.indicator.name
);
} catch (_) {
yield ChartDataLoadFailure(); } } }
This is the bloc_state:
abstract class ChartDataState {
const ChartDataState();
#override
List<Object> get props => []; }
class ChartDataLoadInProgress extends ChartDataState {}
class ChartDataLoadSuccess extends ChartDataState {
final List<List<ChartData>> chartData;
final String titleIndicator;
const ChartDataLoadSuccess(this.chartData,this.titleIndicator);
#override
List<Object> get props => [chartData, titleIndicator];
#override
String toString() => 'ChartDataLoadSuccess { topics: ' + chartData + ' }'; }
class ChartDataLoadFailure extends ChartDataState {}
class DateSliderLoadSuccess extends ChartDataState {
final double dateSlider;
const DateSliderLoadSuccess(this.dateSlider);
#override
List<Object> get props => [dateSlider];
#override
String toString() => 'DateSliderLoadSuccess { dateSlider: ' + dateSlider.toString() + ' }';
}
class DateSliderLoadFailure extends ChartDataState {}
Thanks in advance
Have you tried creating a variable inside your bloc to store the original data?
You would be able to store the data and be able to continue using your bloc and updating your widget.