I'm using Bloc pattern to manage the states of my application , I'm fetching some data from Api , and everything is set up so far , i got stuck in how can i pass a mealID ( the argument i want to pass in bloc to fetch the next api call . i need some help please , Thank you in advance .
- This is my whole bloc code
// bloc events
enum FoodEvent {category,food}
// bloc state
class FoodState {
}
class InitialLoading extends FoodState{
}
class Loading extends FoodState {}
class Error extends FoodState {
String error;
Error(this.error);
}
class Success extends FoodState {
CategoryModel? categoryModel;
Success(this.categoryModel);
}
class FoodSuccess extends FoodState {
FoodModel? foodModel;
FoodSuccess(this.foodModel);
}
// Main Bloc class
class FoodBloc extends Bloc<FoodEvent,FoodState> {
FoodRepository foodRepository = FoodRepository(authService: AuthService());
FoodBloc() : super(InitialLoading()){
on<FoodEvent>(_onFetchEvent);
}
Future<void> _onFetchEvent(FoodEvent event, Emitter<FoodState> emit,) async {
switch(event){
case FoodEvent.category:
emit(Loading());
try {
var categoryModel = await foodRepository.getCategory();
emit(Success(categoryModel));
} catch (e) {
emit(Error(e.toString()));
}
break;
case FoodEvent.food:
emit(Loading());
try {
/// Basically i need o pass mealID which i should receive and pass here from screen
var food = await foodRepository.getFood("1252");
emit(FoodSuccess(food));
} catch (e) {
emit(Error(e.toString()));
}
break;
}
}
}
- Class where i init bloc and show data in ui
class DetailsScreen extends StatefulWidget {
String mealID;
DetailsScreen({Key? key,required this.mealID}) : super(key: key);
@override
State<DetailsScreen> createState() => _DetailsScreenState();
}
class _DetailsScreenState extends State<DetailsScreen> {
late FoodBloc foodBloc;
@override
void didChangeDependencies() {
// Here i initialize my bloc
foodBloc = BlocProvider.of<FoodBloc>(context);
foodBloc.add(FoodEvent.food);
super.didChangeDependencies();
}
@override
void dispose() {
foodBloc.close();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container();
}
}
CodePudding user response:
Passing argument from the UI depends on your usecases, you can pass using the event or updating your state with the value
You may also consider changing your event to the recommended class based
abstract class FoodEvent extends Equatable {
@override
List<Object> get props => [];
}
class CategoryFetched extends FoodEvent {}
class FoodFetched extends FoodEvent {
FoodFetched(this.mealId);
final String mealId;
@override
List<Object> get props => [mealId];
}
So while adding event here just pass the MealId
@override
void didChangeDependencies() {
// Here i initialize my bloc
foodBloc = BlocProvider.of<FoodBloc>(context);
foodBloc.add(FoodFetched(mealId);
super.didChangeDependencies();
}
And your bloc code can be simplified to this:
class FoodBloc extends Bloc<FoodEvent,FoodState> {
FoodRepository foodRepository = FoodRepository(authService: AuthService());
FoodBloc() : super(InitialLoading()){
on<CategoryFetched>(_onCategoryFetched);
on<FoodFetched>(_onFoodFetched);
}
Future<void> _onFoodFetched(FoodFetched event, Emitter<FoodState> emit) async {
try {
var food = await foodRepository.getFood(event.mealId);
emit(FoodSuccess(food));
} catch (e) {
emit(Error(e.toString()));
}
}
Future<void> _onCategoryFetched(CategoryFetched event, Emitter<FoodState> emit) async {
try {
var categoryModel = await foodRepository.getCategory();
emit(Success(categoryModel));
} catch (e) {
emit(Error(e.toString()));
}
}
}