0

I'm using the Bloc package to update my widgets on a Flutter app. I try to update a variable which is a List of favorites. For that I'm getting the state and modifying it to the new value and then I yield the new one(state). The result is cannot see reflected changes  in the current page, but is working in the cloned state(As it is properly loaded in a new tab). What I'm doing wrong as I cannot see the changes reflected in the current state but able to do it in the clone? Please let me know if something is not clear or I should share something else from my codebase. 

Update 1: If I manually do a Hot reload I can see the changes, but I want to accomplish it automatically.

MASTER STATE

import 'package:meta/meta.dart' show required;
import 'package:documentales_app/models/youtube_video.dart';
import 'package:equatable/equatable.dart';

class MasterState extends Equatable {
  final int currentTab;
  final List<YoutubeVideo> history;
  final List<YoutubeVideo> favorites;

  MasterState(
      {@required this.currentTab, @required this.history, this.favorites});

  static MasterState initialState() =>
      MasterState(currentTab: 0, history: [], favorites: []);

  MasterState copyWith(
      {int currentTab,
      List<YoutubeVideo> history,
      List<YoutubeVideo> favorites}) {
    return MasterState(
        currentTab: currentTab ?? this.currentTab,
        history: history ?? this.history,
        favorites: favorites ?? this.favorites);
  }

  @override
  List<Object> get props => [currentTab, history, favorites];
}

MASTER BLOC

Stream<MasterState> _toggleInFavorites(MasterToggleInFavorites event) async* {
    final int index = this
        .state
        .favorites
        .indexWhere((item) => item.videoId == event.youtubeVideo.videoId);

    if (index == -1) {
      final favorites = List<YoutubeVideo>.from(this.state.favorites);
      favorites.add(event.youtubeVideo);
      event.youtubeVideo.isFavorite = true;

      yield this.state.copyWith(favorites: favorites);
    } else {
      final favorites = List<YoutubeVideo>.from(this.state.favorites);
      favorites.removeAt(index);
      event.youtubeVideo.isFavorite = false;

      yield this.state.copyWith(favorites: favorites);
    }
  }

Toggle Button

CupertinoButton(
                        padding: EdgeInsets.zero,
                        minSize: 30,
                        onPressed: () {
                          masterBloc.add(MasterToggleInFavorites(item));
                        },
                        child: CircleContainer(
                          child: Icon(
                            //Icons.playlist_add,
                            item.isFavorite
                                ? Icons.favorite
                                : Icons.favorite_border,
                            color: Colors.white,
                          ),
                          size: 35,
                        ),
                      ),

Favorites tab

import 'package:cached_network_image/cached_network_image.dart';
import 'package:documentales_app/blocs/pages/master_bloc/master_bloc.dart';
import 'package:documentales_app/blocs/pages/master_bloc/master_events.dart';
import 'package:documentales_app/models/youtube_video.dart';
import 'package:share/share.dart';
import 'package:documentales_app/widgets/circle_container.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_youtube/flutter_youtube.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../utils/keys.dart';

class YoutubeVideoItem extends StatelessWidget {
  final VoidCallback onDismissed;
  final YoutubeVideo item;

  const YoutubeVideoItem({@required this.item, this.onDismissed})
      : assert(item != null);

  Widget _getView(MasterBloc masterBloc) {
    return Container(
      child: CupertinoButton(
        padding: EdgeInsets.zero,
        onPressed: () {
          masterBloc.add(MasterAddToHistory(item));
          FlutterYoutube.playYoutubeVideoByUrl(
              apiKey: API_KEY,
              videoUrl: "https://www.youtube.com/watch?v=${item.videoId}",
              autoPlay: true, //default falase
              fullScreen: true //default false
              );
        },
        child: AspectRatio(
          aspectRatio: 12 / 3,
          child: Container(
            margin: EdgeInsets.symmetric(vertical: 5, horizontal: 10),
            padding: EdgeInsets.all(5),
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(10),
              color: Colors.greenAccent,
              boxShadow: [
                BoxShadow(color: Colors.black26, blurRadius: 5),
              ],
            ),
            child: Row(
              children: [
                Expanded(
                  flex: 4,
                  child: ClipRRect(
                    borderRadius: BorderRadius.circular(10),
                    child: CachedNetworkImage(
                      imageUrl: item.banner,
                      fit: BoxFit.cover,
                      height: double.infinity,
                    ),
                  ),
                ),
                Expanded(
                  flex: 5,
                  child: Container(
                    padding: EdgeInsets.all(10),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text(
                          item.title,
                          maxLines: 2,
                          style: TextStyle(
                              fontWeight: FontWeight.w500,
                              color: Colors.white,
                              fontSize: 14),
                        ),
                        SizedBox(
                          height: 5,
                        ),
                        Expanded(
                          child: Text(
                            item.description,
                            overflow: TextOverflow.fade,
                            style: TextStyle(
                                fontWeight: FontWeight.w300,
                                color: Colors.grey[600],
                                fontSize: 13),
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
                Expanded(
                  flex: 1,
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      CupertinoButton(
                        padding: EdgeInsets.zero,
                        minSize: 30,
                        onPressed: () {
                          masterBloc.add(MasterToggleInFavorites(item));
                        },
                        child: CircleContainer(
                          child: Icon(
                            //Icons.playlist_add,
                            item.isFavorite
                                ? Icons.favorite
                                : Icons.favorite_border,
                            color: Colors.white,
                          ),
                          size: 35,
                        ),
                      ),
                      CupertinoButton(
                        padding: EdgeInsets.zero,
                        minSize: 30,
                        onPressed: () {
                          Share.share(
                              'https://www.youtube.com/watch?v=${item.videoId}',
                              subject: 'Mira este impresionante documental');
                        },
                        child: CircleContainer(
                          child: Icon(
                            Icons.share,
                            color: Colors.white,
                          ),
                          size: 35,
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    final masterBloc = BlocProvider.of<MasterBloc>(context);

    if (onDismissed != null) {
      return Dismissible(
        key: Key(item.videoId),
        onDismissed: (_) {
          if (onDismissed != null) {
            onDismissed();
          }
        },
        child: _getView(masterBloc),
      );
    }
    return _getView(masterBloc);
  }
}

Home Tab

import 'package:cached_network_image/cached_network_image.dart';
import 'package:documentales_app/api/account_api.dart';
import 'package:documentales_app/api/youtube_api.dart';
import 'package:documentales_app/models/play_list.dart';
import 'package:documentales_app/models/youtube_video.dart';
import 'package:documentales_app/pages/home_page_widgets/home_tab_shimmer.dart';
import 'package:documentales_app/pages/home_page_widgets/new_videos.dart';
import 'package:documentales_app/pages/home_page_widgets/top_play_lists.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../../utils/keys.dart';

class HomeTab extends StatefulWidget {
  @override
  _HomeTabState createState() => _HomeTabState();
}

class _HomeTabState extends State<HomeTab> {
  AccountApi _accountApi = AccountApi();
  YoutubeApi _youtubeApi = YoutubeApi(apiKey: API_KEY);
  List<dynamic> _users = [];
  List<PlayList> _playlists = [];
  List<YoutubeVideo> _newVideos = [];
  bool _isLoading = true;

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

  _load() async {
    final users = await _accountApi.getUsers(1);
    final List<PlayList> playLists =
        await _youtubeApi.getPlaylists('jklnvfyyklhjh');
    final List<YoutubeVideo> newVideos = await _youtubeApi
        .getPlaylistVideos('PLFXLg_sbbjkGKJbkjgkkGKkgk');
    setState(() {
      _users.addAll(users);
      _playlists.addAll(playLists);
      _newVideos.addAll(newVideos);
      _isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    return ListView(
      children: [
        _isLoading
            ? HomeTabShimmer()
            : Column(
                children: [
                  TopPlayLists(items: _playlists),
                  SizedBox(height: 10),
                  NewVideos(
                    items: _newVideos,
                  ),
                  SizedBox(height: 5),
                ],
              )
      ],
    );
  }
}
Luciano
  • 13
  • 7

1 Answers1

3

Is there only one state?
I know that state is not changed by same name state.

If you want to use current structure like your code.
You need to add another state such as 'MasterStateChanging' between state changes.

<State File>
class MasterStateChanging extends Equatable {
  
}
<Bloc File>
Stream<MasterState> _toggleInFavorites(MasterToggleInFavorites event) async* {
    final int index = this
        .state
        .favorites
        .indexWhere((item) => item.videoId == event.youtubeVideo.videoId);


    yield MasterStateChanging();

    if (index == -1) {
      final favorites = List<YoutubeVideo>.from(this.state.favorites);
      favorites.add(event.youtubeVideo);
      event.youtubeVideo.isFavorite = true;

      yield this.state.copyWith(favorites: favorites);
    } else {
      final favorites = List<YoutubeVideo>.from(this.state.favorites);
      favorites.removeAt(index);
      event.youtubeVideo.isFavorite = false;

      yield this.state.copyWith(favorites: favorites);
    }
  }
KuKu
  • 6,654
  • 1
  • 13
  • 25
  • I'm not sure if I completely understood what you mean. I´ve added in my code tow files. In the favs tab is working properly, but in the home tab is not. It seems that Im not refreshing something in the Home tab, but I cannot get what I'm missing. Any thoughts? Thanks for your time – Luciano Sep 21 '20 at 11:13
  • In brief in the favs tab is working properly, but in the home tab I need to make a manually hot reload to make it work, but it should be changed autmatically as it does on favs tab – Luciano Sep 21 '20 at 11:18