I copy official sample and it works.
but when I change int to viewmodel it won't change value when I click.
How to solve it, thanks.
class MainViewModel {
int selectedColorIndex = -1;
}
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'main_view_model.dart';
void main() {
Bloc.observer = const AppBlocObserver();
runApp(const App());
}
class AppBlocObserver extends BlocObserver {
const AppBlocObserver();
@override
void onChange(BlocBase bloc, Change change) {
super.onChange(bloc, change);
if (bloc is Cubit) print(change);
}
@override
void onTransition(Bloc bloc, Transition transition) {
super.onTransition(bloc, transition);
print(transition);
}
}
class App extends StatelessWidget {
const App({super.key});
@override
Widget build(BuildContext context) {
return AppView();
}
}
class AppView extends StatelessWidget {
const AppView({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: const CounterPage(),
);
}
}
class CounterPage extends StatelessWidget {
const CounterPage({super.key});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (_) => CounterBloc(),
child: const CounterView(),
);
}
}
class CounterView extends StatelessWidget {
const CounterView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Counter')),
body: Center(
child: BlocBuilder<CounterBloc, MainViewModel>(
builder: (context, viewModel) {
return Text(
'${viewModel.selectedColorIndex}',
style: Theme.of(context).textTheme.displayLarge,
);
},
),
),
floatingActionButton: Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
FloatingActionButton(
child: const Icon(Icons.add),
onPressed: () {
context.read<CounterBloc>().add(CounterIncrementPressed());
},
),
const SizedBox(height: 4),
FloatingActionButton(
child: const Icon(Icons.remove),
onPressed: () {
context.read<CounterBloc>().add(CounterDecrementPressed());
},
),
],
),
);
}
}
abstract class CounterEvent {}
class CounterIncrementPressed extends CounterEvent {}
class CounterDecrementPressed extends CounterEvent {}
class CounterBloc extends Bloc<CounterEvent, MainViewModel> {
CounterBloc() : super(MainViewModel()) {
on<CounterIncrementPressed>((event, emit) {
state.selectedColorIndex + 1;
emit(state);
});
on<CounterDecrementPressed>((event, emit) {
state.selectedColorIndex - 1;
emit(state);
});
}
}
The issue is that you're not updating the state correctly inside your event handlers. You need to create a new instance of MainViewModel with the updated value and emit it. Emitting the same object will not trigger a state update in the Bloc
class MainViewModel {
final int selectedColorIndex;
MainViewModel({this.selectedColorIndex = 0});
MainViewModel copyWith({int? selectedColorIndex}) {
return MainViewModel(
selectedColorIndex: selectedColorIndex ?? this.selectedColorIndex,
);
}
}
class CounterBloc extends Bloc<CounterEvent, MainViewModel> {
CounterBloc() : super(MainViewModel()) {
on<CounterIncrementPressed>((event, emit) {
emit(state.copyWith(selectedColorIndex: state.selectedColorIndex + 1));
});
on<CounterDecrementPressed>((event, emit) {
emit(state.copyWith(selectedColorIndex: state.selectedColorIndex - 1));
});
}
}