Toogle Favorites in onDismissable event in Flutter with Bloc



我在完成与如何从列表中添加/删除(切换(收藏夹(来自api响应(相关的操作时遇到了一些问题。事实上,我可以将最喜欢的添加到列表中,也可以以单独的方式将其删除,但我不能以切换的方式使用相同的按钮。简而言之,它正在工作,但我无法正确实现切换操作。请你看一下代码,看看是否有一个很好的方法可以在不使用setstate的情况下实现切换?

取消(从列表中删除(的按钮

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

使用Bloc 实现将收藏夹添加到列表的相同按钮

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

项目定义

class YoutbeVideo {
final String videoId, title, description, banner;
bool isFavorite;
YoutbeVideo(
{@required this.videoId,
@required this.title,
@required this.description,
@required this.banner,
this.isFavorite});
void toggleFavoriteStatus() {
isFavorite = !isFavorite;
}


BloC代码分为3个文件

主位置

import 'package:bloc/bloc.dart';
import 'package:documentales_app/models/youtube_video.dart';
import 'master_events.dart';
import 'master_state.dart';
class MasterBloc extends Bloc<MasterEvents, MasterState> {
@override
MasterState get initialState => MasterState.initialState();
@override
Stream<MasterState> mapEventToState(MasterEvents event) async* {
if (event is MasterSetTab) {
yield this.state.copyWith(currentTab: event.tab);
} else if (event is MasterAddToHistory) {
yield* _addToHistory(event);
} else if (event is MasterRemoveFromHistory) {
yield* _removeFromHistory(event);
} else if (event is MasterRemoveFromFavorites) {
yield* _removeFromFavorites(event);
} else if (event is MasterLogout) {
yield this.state.copyWith(history: [], currentTab: 0);
} else if (event is MasterAddToFavorites) {
yield* _addToFavorites(event);
}
}
Stream<MasterState> _addToHistory(MasterAddToHistory event) async* {
final int index = this
.state
.history
.indexWhere((item) => item.videoId == event.youtubeVideo.videoId);
if (index == -1) {
final history = List<YoutubeVideo>.from(this.state.history);
history.add(event.youtubeVideo);
yield this.state.copyWith(history: history);
}
}
Stream<MasterState> _addToFavorites(MasterAddToFavorites 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);
yield this.state.copyWith(favorites: favorites);
}
}
Stream<MasterState> _removeFromHistory(MasterRemoveFromHistory event) async* {
final history = List<YoutubeVideo>.from(this.state.history);
history.removeAt(event.index);
yield this.state.copyWith(history: history);
}
Stream<MasterState> _removeFromFavorites(
MasterRemoveFromFavorites event) async* {
final favorites = List<YoutubeVideo>.from(this.state.favorites);
favorites.removeAt(event.index);
yield this.state.copyWith(favorites: favorites);
}
}

主状态

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

主事件

import 'package:documentales_app/models/youtube_video.dart';
abstract class MasterEvents {}
class MasterSetTab extends MasterEvents {
final int tab;
MasterSetTab(this.tab);
}
class MasterAddToHistory extends MasterEvents {
final YoutubeVideo youtubeVideo;
MasterAddToHistory(this.youtubeVideo);
}
class MasterAddToFavorites extends MasterEvents {
final YoutubeVideo youtubeVideo;
MasterAddToFavorites(this.youtubeVideo);
}
class MasterRemoveFromHistory extends MasterEvents {
final int index;
MasterRemoveFromHistory(this.index);
}
class MasterRemoveFromFavorites extends MasterEvents {
final int index;
MasterRemoveFromFavorites(this.index);
}

因此,执行切换的一种方法是用一个事件替换Add和Remove事件。所以你可以摆脱这些事件:

class MasterAddToFavorites extends MasterEvents {
final YoutubeVideo youtubeVideo;
MasterAddToFavorites(this.youtubeVideo);
}
class MasterRemoveFromFavorites extends MasterEvents {
final int index;
MasterRemoveFromFavorites(this.index);
}

并将其替换为:

class MasterToggleInFavorites extends MasterEvents {
final YoutubeVideo video;
MasterToggleInFavorites(video);
}

接下来,在集团内部,在处理该事件的方法内部,您可以这样做:

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.isFavourite = true;
yield this.state.copyWith(favorites: favorites);
} else {
final favorites = List<YoutubeVideo>.from(this.state.favorites);
favorites.removeAt(index);
event.youtubeVideo.isFavourite = false;
yield this.state.copyWith(favorites: favorites);
}

视频类

class YoutubeVideo {
final String videoId, title, description, banner;
bool isFavorite;
YoutubeVideo(
{@required this.videoId,
@required this.title,
@required this.description,
@required this.banner,
this.isFavorite = false});
factory YoutubeVideo.fromJson(Map<String, dynamic> json,
{bool fromPlayList = false}) {
final snippet = json['snippet'];
final thumbnail =
snippet['thumbnails']['standard'] ?? snippet['thumbnails']['high'];
String videoId;
if (!fromPlayList) {
videoId = json['contentDetails']['videoId'];
} else {
videoId = snippet['resourceId']['videoId'];
}
return YoutubeVideo(
videoId: videoId,
title: snippet['title'],
description: snippet['description'],
banner: thumbnail['url']);
}
}

这是按下的动作,但由于任何原因都不能反映的颜色变化

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

最新更新