Mahmoud Mabrouk
Mahmoud Mabrouk

Reputation: 733

Flutter bloc: updating the state does not re-call BlocBuilder

I have a page being managed using bloc

here is the home_state.dart

import 'package:banha/data/models/category.dart';
import 'package:flutter/material.dart';

abstract class HomeState {
  HomeState() : super();
}

class HomeInitial extends HomeState {}

class UpdateCats extends HomeState {
  final List<Category> cats;
  final int rand;
  UpdateCats({@required this.cats,@required this.rand}){
    print(this.cats);
    print(this.rand);
  }
}

and the home_bloc.dart (note: the Random number is just to make sure the state is diff from the prev one)

import 'dart:math';

import 'package:banha/data/models/category.dart';
import 'package:banha/data/network/categories.dart';
import 'package:banha/ui/tabs/home/bloc/home_events.dart';
import 'package:banha/ui/tabs/home/bloc/home_states.dart';
import 'package:bloc/bloc.dart';

class HomeBloc extends Bloc<HomeEvents, HomeState> {
  getAllCats() {
    dispatch(HomeGetCategories());
  }

  HomeBloc() : super();

  @override
  HomeState get initialState => HomeInitial();

  @override
  Stream<HomeState> mapEventToState(HomeEvents event) async* {
    if (event is HomeGetCategories) {
      yield* _getCats();
    }
  }

  Stream<HomeState> _getCats() async* {
    print("getting cats");
    List<Category> newCats;
    await Network_getAllCategories().then((List<Category> cats) {
      newCats = cats;
    });
    yield UpdateCats(cats: newCats, rand: Random().nextInt(21312545));
  }
}

and the page widget:

import 'package:banha/ui/category/category.dart';
import 'package:banha/ui/tabs/home/bloc/home_bloc.dart';
import 'package:banha/ui/tabs/home/bloc/home_states.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

class ListingsWidget extends StatefulWidget {
  @override
  _ListingsWidgetState createState() => _ListingsWidgetState();
}

class _ListingsWidgetState extends State<ListingsWidget> {
  final HomeBloc _homeBloc = HomeBloc();

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 130,
      padding: EdgeInsets.only(top: 10, bottom: 10),
      child: BlocListener(
        bloc: _homeBloc,
        listener: (context, state) {
          print(state);
        },
        child: BlocBuilder<HomeBloc, HomeState>(
          bloc: _homeBloc,
          builder: (BuildContext context,HomeState state) {
            if(state is UpdateCats){
              print(state.cats);
            }
            return ListView(
              scrollDirection: Axis.horizontal,
              children: <Widget>[
                InkWell(
                  borderRadius: BorderRadius.circular(1000),
                  onTap: () {
                    HomeBloc().getAllCats();
//                    Navigator.push(context, CupertinoPageRoute(builder: (context) => CategoryPage()));
                  },
....

the issue is that in the view(Widget) BlocBuilder is just being called once on initial, but when I try to test changing the state using HomeBloc().getAllCats(); and then print the new State using this code:

if(state is UpdateCats){
              print(state.cats);
            }

nothing happens (Builder is not being called ever again), what's wrong with my code?

Upvotes: 1

Views: 5022

Answers (2)

Fernando Santos
Fernando Santos

Reputation: 432

The problem is here:

...
onTap: () {
...
  HomeBloc().getAllCats();
...
},
...

It should be _homeBloc.getAllCats();

Upvotes: 2

Mahmoud Mabrouk
Mahmoud Mabrouk

Reputation: 733

I added BlocProvider to the root widget (which is HomePage) and that fixed the issue.

Upvotes: 0

Related Questions