4

I am making a movie list application in Flutter and when I open the app I am displaying most-viewed movies list. When I click a button, I fetch new data and add it to the sink which is then sent to the StreamBuilder and should refresh the screen with new data.
But that doesn't happen. I cannot fathom why!

Here is my code for the Repository:

class MoviesRepository {
  final _movieApiProvider = MovieApiProvider();

  fetchAllMovies() async => _movieApiProvider.fetchMovieList();

  fetchAllSimilarMovies(genreIdeas) async => await _movieApiProvider.fetchMoviesLikeThis(genreIdeas);

  fetchTopRatedMovies() async => await _movieApiProvider.fetchTopRatedMovieList();
}

Here is my code for bloc:

class MoviesBloc {

  final _moviesRepository = MoviesRepository();
  final _moviesFetcher = BehaviorSubject<Result>();

  Sink<Result> get allMovies => _fetcherController.sink;
  final _fetcherController = StreamController<Result>();

  Observable<Result> get newResults => _moviesFetcher.stream;

  fetchAllMovies() async {
    Result model = await _moviesRepository.fetchAllMovies();
    allMovies.add(model);
  }

  fetchTopRatedMovies() async{
    Result model = await _moviesRepository.fetchTopRatedMovies();
    allMovies.add(model);
  }

  dispose() {
    _moviesFetcher.close();
    _fetcherController.close();
  }

  MoviesBloc() {
    _fetcherController.stream.listen(_handle);
  }


  void _handle(Result event) {

    _moviesFetcher.add(event);

  }
}

final bloc = MoviesBloc();

UPDATE

And here is my code for the StreamBuilder:

class HomeScreenListState extends State<HomeScreenList> {
  @override
  void initState() {
    super.initState();
    print("init");
    bloc.fetchAllMovies();
  }

  @override
  void dispose() {
    super.dispose();
    bloc.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<Result>(
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          print("new data is here");
          return buildList(snapshot);
        } else if (snapshot.hasError) {
          return Text('Error!!');
        }

        return Center(
          child: CircularProgressIndicator(),
        );
      },
      stream: bloc.newResults,
    );
  }
}

And this is the button that triggers to get new data and add it to the sink:

child: RaisedButton(onPressed: () {
                    bloc.fetchTopRatedMovies();
                  },

This button fetches top-rated movies and add to the same sink. Now the StreamBuilder should pick up the new data as I think.

Where is the problem??

Dhruvam Sharma
  • 1,661
  • 14
  • 22
  • Which part is not working? Is the new result added to the `allMovies` sink? Does `_handle` get called? The code looks like it should work as far as I can tell. – Edman Jan 30 '19 at 17:52
  • @Edman Sorry for such a late reply, but after a lot of debugging, allMovies sink does get called. And the _handle is called too. Widget rebuilding does not take place. I have updated the last part of the code to add logs whenever widget is built but that is only called once when the app launches. – Dhruvam Sharma Mar 24 '19 at 13:09
  • 1
    @Dhruvam Sharma i am following the same example as u but in my case the streambuilder snapshot has no data(not null) any suggestions? – Lekr0 May 13 '19 at 12:24
  • @Lekr0 I suggest that you use BehaviourSubject instead of Stream Controller. It will make your task easier. – Dhruvam Sharma May 13 '19 at 14:07

1 Answers1

0

You can use Equatable alongside your BLoC implementation to manage state changes on your screen. Here's a guide that I suggest trying out.

Omatt
  • 8,564
  • 2
  • 42
  • 144