Flutter Bloc, UI not updating when state is emmited - flutter

I have an app where I'm emitting budgetLoaded() in several events. I have noticed that if I don't emit a different state with my budgetLoading even the app doesn't seem to respond to the change.
import 'package:bloc/bloc.dart';
import 'package:budget_app/model/budget.dart';
import 'package:budget_app/model/budget_repository.dart';
import 'package:equatable/equatable.dart';
part 'budget_event.dart';
part 'budget_state.dart';
class BudgetBloc extends Bloc<BudgetEvent, BudgetState> {
final BudgetRepository budgetRepository;
BudgetBloc({required this.budgetRepository}) : super(BudgetInitial()) {
on<AppStarted>((event, emit) async {
emit(BudgetLoading());
if (await budgetRepository.hasBudget()) {
emit(BudgetLoaded(budget: budgetRepository.budget));
} else {
emit(BudgetLoaded(budget: budgetRepository.budget));
}
});
on<Withdraw>((event, emit) {
budgetRepository.budget.withdraw(event.amount);
emit(BudgetLoaded(budget: budgetRepository.budget));
});
on<Deposit>((event, emit) {
emit(BudgetLoading());
budgetRepository.budget.deposit(event.amount);
emit(new BudgetLoaded(budget: budgetRepository.budget));
});
}
}
This is an issue with the deposit event. This code works.
import 'package:bloc/bloc.dart';
import 'package:budget_app/model/budget.dart';
import 'package:budget_app/model/budget_repository.dart';
import 'package:equatable/equatable.dart';
part 'budget_event.dart';
part 'budget_state.dart';
class BudgetBloc extends Bloc<BudgetEvent, BudgetState> {
final BudgetRepository budgetRepository;
BudgetBloc({required this.budgetRepository}) : super(BudgetInitial()) {
on<AppStarted>((event, emit) async {
emit(BudgetLoading());
if (await budgetRepository.hasBudget()) {
emit(BudgetLoaded(budget: budgetRepository.budget));
} else {
emit(BudgetLoaded(budget: budgetRepository.budget));
}
});
on<Withdraw>((event, emit) {
budgetRepository.budget.withdraw(event.amount);
emit(BudgetLoaded(budget: budgetRepository.budget));
});
on<Deposit>((event, emit) {
budgetRepository.budget.deposit(event.amount);
emit(new BudgetLoaded(budget: budgetRepository.budget));
});
}
}
This code does not work the state that is emitted is correct, I have unit tests to test this and I've done debugging.
This is the main page, the BlocProvider is in the Main file above the Material App so it should be global.
import 'package:budget_app/bloc/budget_bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class WalletScreen extends StatefulWidget {
const WalletScreen({Key? key}) : super(key: key);
#override
State<WalletScreen> createState() => _WalletScreenState();
}
class _WalletScreenState extends State<WalletScreen> {
#override
Widget build(BuildContext context) {
var theme = Theme.of(context);
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () => onPressed(context),
child: Icon(Icons.add),
),
body: BlocBuilder<BudgetBloc, BudgetState>(
bloc: BlocProvider.of<BudgetBloc>(context),
builder: (context, state) {
if (state is BudgetLoaded) {
var budget = state.budget;
return SafeArea(
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(10.0),
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Container(
child: Center(
child: Column(
children: [
Text(
'Current Balance:',
style: TextStyle(
color: Colors.white, fontSize: 25),
),
Text(
'${budget.numberFormatted}',
style: TextStyle(
color: Colors.green, fontSize: 50),
),
],
),
),
color: Colors.blueGrey,
),
),
),
],
),
),
);
} else {
return CircularProgressIndicator();
}
},
),
);
}
onPressed(BuildContext context) {
var budgetBloc = BlocProvider.of<BudgetBloc>(context);
budgetBloc.add(Deposit(100.00));
}
}
It's not a huge issue I just want to understand why it doesn't work.
EVENT
part of 'budget_bloc.dart';
abstract class BudgetEvent extends Equatable {
const BudgetEvent();
#override
List<Object> get props => [];
}
class AppStarted extends BudgetEvent {}
class Withdraw extends BudgetEvent {
final double amount;
const Withdraw(this.amount);
}
class Deposit extends BudgetEvent {
final double amount;
const Deposit(this.amount);
}
STATE
part of 'budget_bloc.dart';
abstract class BudgetState extends Equatable {
const BudgetState();
#override
List<Object> get props => [];
}
class BudgetInitial extends BudgetState {}
class BudgetLoading extends BudgetState {}
class BudgetLoaded extends BudgetState {
final Budget budget;
BudgetLoaded({required this.budget});
}

You can see in the source of emit that it won't publish a state if it is equal to the last one:
void emit(State state) {
try {
if (isClosed) {
throw StateError('Cannot emit new states after calling close');
}
if (state == _state && _emitted) return;
onChange(Change<State>(currentState: this.state, nextState: state));
_state = state;
_stateController.add(_state);
_emitted = true;
} catch (error, stackTrace) {
onError(error, stackTrace);
rethrow;
}
}
By default, == returns true if two objects are the same instance. This could lead to redundant state change notifications, so we usually override == and hashCode, to explicitly tell what counts as equal.
In your example Equatable overrides == and hashCode for you so you don't have to write boilerplate code. The problem is, your props list is empty, so every instance of the same class will be equal to each other. This is why you don't see a state change after the first one.
You should override the props in BudgetLoaded, so Equatable knows what should be compared:
class BudgetLoaded extends BudgetState {
final Budget budget;
BudgetLoaded({required this.budget});
#override
List<Object> get props => [budget];
}
And don't forget to update the Budget class too so that == and hashCode say they are equal, when you think they should be equal.

Related

Why isn't the screen rebuild in flutter bloc?

I split the screen into 2 parts, the upper part to change the state when each time I clicked, the bottom part is a list, when the state is loaded, I try to add an event to sort, it still works but the screen don't rebuild again
My code here
Hope everyone can help! Thank
widget
Scaffold(
backgroundColor: Colors.white,
body: SafeArea(
child: BlocProvider(
create: (_) => referrerBloc,
child: Column(
children: [
flag1(referrerBloc.add(ReferrerSortEvent)),
flag2(referrerBloc.add(ReferrerSortEvent)),
flag3(referrerBloc.add(ReferrerSortEvent)),
BlocBuilder<ReferrerBloc, ReferrerState>(
builder: (__, state) {
if (state is ReferrerLoadingState) {
referrerBloc.add(ReferrerLoadedEvent());
return const Center(
child: CircularProgressIndicator(),
);
} else if (state is ReferrerLoadedState) {
final listReferrer = state.listReferrer;
return Expanded(
child: ListView.builder(
itemCount: listReferrer.length,
itemBuilder: (context, index) {
return Container(
padding: const EdgeInsets.symmetric(
horizontal: 16,
),
child: itemUser(listReferrer.elementAt(index)),
);
},
),
);
}
return const Center(
child: Text(
'Error!',
style: TextStyle(color: Colors.red),
),
);
},
),
],
),
),
),
)
My code here Hope everyone can help! Thank
My code here Hope everyone can help! Thank
event
part of 'referrer_bloc.dart';
abstract class ReferrerEvent extends Equatable {
const ReferrerEvent();
#override
List<Object> get props => [];
}
class ReferrerLoadingEvent extends ReferrerEvent {}
class ReferrerLoadedEvent extends ReferrerEvent {}
class ReferrerSortEvent extends ReferrerEvent {
const ReferrerSortEvent({required this.flag, required this.time});
final int flag;
final int time;
}
class ReferrerErrorEvent extends ReferrerEvent {}
My code here Hope everyone can help! Thank
My code here Hope everyone can help! Thank
state
part of 'referrer_bloc.dart';
abstract class ReferrerState extends Equatable {
const ReferrerState();
}
class ReferrerLoadingState extends ReferrerState {
const ReferrerLoadingState();
#override
List<Object> get props => [];
}
class ReferrerLoadedState extends ReferrerState {
const ReferrerLoadedState({required this.listReferrer});
final List<ItemReferrer> listReferrer;
#override
List<Object> get props => [listReferrer];
}
My code here Hope everyone can help! Thank
My code here Hope everyone can help! Thank
bloc
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:helloapp/referrer/models/item_referrer.dart';
part 'referrer_event.dart';
part 'referrer_state.dart';
class ReferrerBloc extends Bloc<ReferrerEvent, ReferrerState> {
ReferrerBloc() : super(const ReferrerLoadingState()) {
on<ReferrerEvent>((event, emit) {
});
on<ReferrerLoadedEvent>((event, emit) {
final listUser = [
Item1,
......
];
emit(ReferrerLoadedState(listReferrer: listUser));
});
on<ReferrerSortEvent>((event, emit) {
print(event.flag);
final listUser = [
Item1,
........
];
final List<ItemReferrer> listResult = [];
if (event.flag == 0) {
listUser.forEach(listResult.add);
} else if (event.flag == 1) {
listUser.forEach((element) {
if (element.flag == 1) {
listResult.add(element);
}
});
}
emit(ReferrerLoadedState(listReferrer: listResult));
});
}
}
You can use TabBar instead of Column.
Here's the official link of Flutter: https://docs.flutter.dev/cookbook/design/tabs

Problem with events in BLoC Flutter. I always call two events instead of one

I return the state with the TodoLoadedState list in each block method. But when I call the block event in onPressed, the list itself is not returned and I have to add a second call to the block method todoBloc.add(LoadTodos()); But that's not correct. Ideas need to trigger 1 event but to perform 2 actions, the second action is to update the list. Thanks in advance!
todo_bloc
class TodoBloc extends Bloc<TodoEvent, TodoState> {
final TodoRepository todoRepository;
TodoBloc(this.todoRepository) : super(TodoEmptyState()) {
on<LoadTodos>((event, emit) async {
emit(TodoLoadingState());
try {
final List<Todo> _loadedTodoList = await todoRepository.getAllTodos();
emit(TodoLoadedState(loadedUser: _loadedTodoList));
} catch (_) {
emit(TodoErrorState());
}
});
on<CreateTodos>((event, emit) async {
// Todo todo = Todo(description: event.task, isDone: false);
await todoRepository.insertTodo(event.todo);
final List<Todo> _loadedTodoList = await todoRepository.getAllTodos();
emit(TodoLoadedState(loadedUser: _loadedTodoList));
});
on<DeleteTodos>((event, emit) async {
await todoRepository.deleteTodo(event.id);
final List<Todo> _loadedTodoList = await todoRepository.getAllTodos();
emit(TodoLoadedState(loadedUser: _loadedTodoList));
});
on<UpdateTodos>((event, emit) async {
await todoRepository.updateTodo(event.todo);
final List<Todo> _loadedTodoList = await todoRepository.getAllTodos();
emit(TodoLoadedState(loadedUser: _loadedTodoList));
});
}
}
todo_list
class TodoList extends StatelessWidget {
#override
Widget build(BuildContext context) {
final TodoBloc todoBloc = context.read<TodoBloc>();
return BlocBuilder<TodoBloc, TodoState>(builder: (context, state) {
if (state is TodoEmptyState) {
return const Center(
child: Text(
'No Todo',
style: TextStyle(fontSize: 20.0),
),
);
}
if (state is TodoLoadingState) {
return const Center(child: CircularProgressIndicator());
}
if (state is TodoLoadedState) {
return ListView.builder(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: state.loadedUser.length,
itemBuilder: (context, index) => ListTile(
title: Column(children: [
Text('${state.loadedUser[index].description}'),
Text('${state.loadedUser[index].id}'),
]),
trailing: IconButton(
onPressed: () {
todoBloc.add(DeleteTodos(id: state.loadedUser[index].id));
todoBloc.add(LoadTodos());
},
home_page
class HomePage extends StatelessWidget {
final todoRepository = TodoRepository();
#override
Widget build(BuildContext context) {
return BlocBuilder<TodoBloc, TodoState>(builder: (context, state) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter Todos'),
),
body: SingleChildScrollView(
child: Column(
children: [
TodoList(),
],
),
),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add, size: 32, color: Colors.white),
onPressed: () {
final TodoBloc todoBloc = context.read<TodoBloc>();
final _todoDescriptionFromController = TextEditingController();
showModalBottomSheet(
context: context,
builder: (builder) {
return Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: Container(
color: Colors.transparent,
child: Container(
todo_state
abstract class TodoState extends Equatable {
const TodoState();
#override
List<Object> get props => [];
}
class TodoLoadingState extends TodoState {}
class TodoEmptyState extends TodoState {}
class TodoLoadedState extends TodoState {
List<dynamic> loadedUser;
TodoLoadedState({required this.loadedUser});
}
class TodoErrorState extends TodoState {}
todo_event
abstract class TodoEvent extends Equatable {
const TodoEvent();
#override
List<Object> get props => [];
}
class LoadTodos extends TodoEvent {}
class CreateTodos extends TodoEvent {
final Todo todo;
const CreateTodos(this.todo);
}
class UpdateTodos extends TodoEvent {
final Todo todo;
const UpdateTodos(this.todo);
}
class DeleteTodos extends TodoEvent {
final int id;
const DeleteTodos({required this.id});
}
class QueryTodo extends TodoEvent {}
event onPressed, everywhere you have to use 2 events to load the updated list
todoBloc.add(UpdateTodos(updateTodo));
todoBloc.add(LoadTodos());
This is the culprit:
abstract class TodoState extends Equatable {
const TodoState();
#override
List<Object> get props => [];
}
You are extending Equatable in TodoState and passing an empty list to props. When other states such as TodoLoadedState extend TodoState they inherit Equatable as well and the empty props.
If you're using Equatable make sure to pass all properties to the
props getter.
This is from bloc faq. Right now all instances of your TodoLoadedState are considered equal. Doesn't matter if you have a TodoLoadedState with hundreds of loadedUser or a TodoLoadedState with none. They are both considered equal and only the first time you pass a new TodoLoadedState the BlocBuilder will update. The consequent ones have no effect since BlocBuilder thinks it is the same as previous one. The reason your LoadTodos event causes a rebuild is that first you emit TodoLoadingState() and then in case of success TodoLoadedState(loadedUser: _loadedTodoList). This alternating between two different states makes it work.
So either don't use Equatable or make sure to pass all the properties to props.
class TodoLoadedState extends TodoState {
final List<dynamic> loadedUser;
TodoLoadedState({required this.loadedUser});
#override
List<Object?> get props => [loadedUser];
}

Flutter: Bloc not working after executing for the first time

I'm trying to execute Bloc more times than one, however I don't know how to handle that.
When I click search, it shows circular progress indicator and then the "Sukces" text, but when i click it for the second time, the indicator doesn't show.
How to fix it?
Link to the video of my app: https://streamable.com/77jyf1
My code:
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:jaki_to_bank/screens/home/bloc/search_bloc.dart';
import 'package:provider/provider.dart';
import 'package:jaki_to_bank/generated/l10n.dart';
import 'package:jaki_to_bank/screens/home/widgets/search_button.dart';
import 'package:jaki_to_bank/screens/home/widgets/search_text_field.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({Key? key}) : super(key: key);
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
final _formKey = GlobalKey<FormState>();
final SearchBloc _bloc = SearchBloc();
final TextEditingController _bankAccountController = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(S.current.title),
),
body: Container(
padding: EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: Column(
children: [
SearchTextField(
controller: _bankAccountController,
validator: (text) {
if (text == null || text.isEmpty) {
return S.current.emptyFieldError;
}
return null;
},
),
SizedBox(height: 16.0),
SearchButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
final validationBloc = context.read<SearchBloc>();
validationBloc.add(GetText(_bankAccountController.text));
}
},
),
BlocBuilder<SearchBloc, SearchState>(
builder: (context, state) {
if (state is SearchInitial) {
return Container();
}
if (state is SearchLoading) {
return CircularProgressIndicator();
}
if (state is SearchFinal) {
return Text('Sukces!');
}
return Container();
},
)
],
),
),
),
);
}
}
part of 'search_bloc.dart';
#immutable
abstract class SearchEvent {}
class GetText extends SearchEvent {
final String bankAccountNumber;
GetText(this.bankAccountNumber);
}
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart';
import 'package:jaki_to_bank/data/repositories/bank_repository.dart';
import 'package:meta/meta.dart';
import 'package:xml/xml.dart';
part 'search_event.dart';
part 'search_state.dart';
class SearchBloc extends Bloc<SearchEvent, SearchState> {
SearchBloc() : super(SearchInitial());
#override
Stream<SearchState> mapEventToState(
SearchEvent event,
) async* {
if (event is GetText) {
yield SearchLoading();
final String bankAccountNumber = event.bankAccountNumber;
final String bankIdNumber = bankAccountNumber.substring(2, 5);
final BankRepository bankRepo = BankRepository();
final List<String> bankIdsList = <String>[];
final XmlDocument banks = await bankRepo.getParsedXmlText();
final Iterable<XmlElement> bankIds =
banks.findAllElements('NrInstytucji');
bankIds.map((node) => node.text).forEach((element) {
print(element);
});
yield SearchFinal();
}
}
}
part of 'search_bloc.dart';
#immutable
abstract class SearchState {}
class SearchInitial extends SearchState {
SearchInitial();
}
class SearchLoading extends SearchState {
SearchLoading();
}
class SearchFinal extends SearchState {
SearchFinal();
}

how could i check connectivity using cubit?

I need to check the connectivity in every page inside my application using connectivity library,
So i will use a cubit inside the provider. the question is when to close the stream to make it possible to dispose it when the user close the app?
just like this:
import 'package:connectivity/connectivity.dart';
#override
dispose() {
super.dispose();
subscription.cancel();
}
1. Make sure you have imported flutter_bloc and connectivity_plus in your pubspec.yaml.
2. Create an InternetCubit files:
internet_cubit.dart
internet_state.dart
3. internet_state.dart:
Here we create enum with connection types for our cubit and cubit states:
part of 'internet_cubit.dart';
enum ConnectionType {
wifi,
mobile,
}
#immutable
abstract class InternetState {}
class InternetLoading extends InternetState {}
class InternetConnected extends InternetState {
final ConnectionType connectionType;
InternetConnected({#required this.connectionType});
}
class InternetDisconnected extends InternetState {}
4. internet_cubit.dart:
Cubit depends on connectivity plugin, so we import it and create a stream subscription to be able to react on connection changes.
Also we define two methods emitInternetConnected and emitInternetDisconnected that will change actual cubit state.
Make sure to dispose of stream subscription properly.
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:meta/meta.dart';
part 'internet_state.dart';
class InternetCubit extends Cubit<InternetState> {
final Connectivity connectivity;
StreamSubscription connectivityStreamSubscription;
InternetCubit({#required this.connectivity})
: assert(connectivity != null),
super(InternetLoading()) {
connectivityStreamSubscription =
connectivity.onConnectivityChanged.listen((connectivityResult) {
if (connectivityResult == ConnectivityResult.wifi) {
emitInternetConnected(ConnectionType.wifi);
} else if (connectivityResult == ConnectivityResult.mobile) {
emitInternetConnected(ConnectionType.mobile);
} else if (connectivityResult == ConnectivityResult.none) {
emitInternetDisconnected();
}
});
}
void emitInternetConnected(ConnectionType _connectionType) =>
emit(InternetConnected(connectionType: _connectionType));
void emitInternetDisconnected() => emit(InternetDisconnected());
#override
Future<void> close() {
connectivityStreamSubscription.cancel();
return super.close();
}
}
5. In your app main file create an instance of Connectivity plugin and pass it to your BlocProvider. Set up bloc consuming with your needs:
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/material.dart';
import 'package:flutter_application_4/cubit/internet_cubit.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
void main() => runApp(MyApp(connectivity: Connectivity()));
class MyApp extends StatelessWidget {
final Connectivity connectivity;
const MyApp({Key key, this.connectivity}) : super(key: key);
#override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => InternetCubit(connectivity: connectivity),
child: MaterialApp(
title: 'Connectivity cubit',
home: Scaffold(
appBar: AppBar(
title: Text('Connectivity cubit spotlight'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
BlocBuilder<InternetCubit, InternetState>(
builder: (context, state) {
if (state is InternetConnected &&
state.connectionType == ConnectionType.wifi) {
return Text(
'Wifi',
style: TextStyle(color: Colors.green, fontSize: 30),
);
} else if (state is InternetConnected &&
state.connectionType == ConnectionType.mobile) {
return Text(
'Mobile',
style: TextStyle(color: Colors.yellow, fontSize: 30),
);
} else if (state is InternetDisconnected) {
return Text(
'Disconnected',
style: TextStyle(color: Colors.red, fontSize: 30),
);
}
return CircularProgressIndicator();
},
),
],
),
),
),
),
);
}
}

Flutter BLoc pass parameters

I'm trying to pass parameters to a bloc event following the bloc pattern, I have found this article however my dart document couldn't find the dispatch (event) method.
Flutter BLoC - How to pass parameter to event?
How do I pass parameters to something like this
main.dart
this works
_counterBloc.add(Counter.increment);
But this doesn't
_counterBloc.add(Counter.increment(3));
bloc.dart
import 'package:bloc/bloc.dart';
enum CounterEvents { increment }
class CounterBloc extends Bloc<CounterEvents, int> {
#override
int get initialState => 0;
#override
Stream<int> mapEventToState(CounterEvents event) async* {
switch (event) {
case CounterEvents.increment:
print(event);
yield state + 1;
break;
}
}
}
you should write CounterEvent like below:
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
enum EventStatus { INCREMENT, DECREMENT }
class CounterEvent {
final int value;
final EventStatus status;
const CounterEvent({#required this.value, #required this.status});
}
class CounterBLoC extends Bloc<CounterEvent, int> {
#override
int get initialState => 0;
#override
Stream<int> mapEventToState(event) async* {
if (event.status == EventStatus.INCREMENT) {
yield state + event.value;
} else if (event.status == EventStatus.DECREMENT) {
yield state - event.value;
}
}
}
and use them in the widget like below:
#override
Widget build(BuildContext context) {
final counterBloc = BlocProvider.of<CounterBLoC>(context);
return Scaffold(
body: Center(
child: BlocBuilder<CounterBLoC, int>(
builder: (ctx, state) {
return Text(
'count: $state',
style: TextStyle(fontSize: 28),
);
},
),
),
floatingActionButton: Align(
alignment: Alignment.bottomRight,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
FloatingActionButton(
onPressed: () {
counterBloc
.add(CounterEvent(value: 5, status: EventStatus.INCREMENT));
},
child: Icon(Icons.add_circle),
),
FloatingActionButton(
onPressed: () {
counterBloc
.add(CounterEvent(value: 5, status: EventStatus.DECREMENT));
},
child: Icon(Icons.remove_circle),
),
],
),
),
);
}
make sure to init your bloc in the main :
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: BlocProvider<CounterBLoC>(
create: (ctx) => CounterBLoC(),
child: TestBlocWidget(),
),
);
}
}
If you are trying to rebuild the Counter App using bloc patter,
Go through this article this may help.
https://bloclibrary.dev/#/fluttercountertutorial?id=counter-app
Consider making a custom event. Your solution should be something like this (haven't checked for bugs, but the paradigm is correct):
abstract class CounterEvent {}
class Increment extends CounterEvent {
int amount;
Increment({this.amount});
}
Then in your bloc:
class CounterBloc extends Bloc<CounterEvent, int> {
#override
int get initialState => 0;
#override
Stream<int> mapEventToState(CounterEvent event) async* {
if (event is Increment) {
yield state + event.amount;
}
}
}