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),
],
)
],
);
}
}