使用Bloc在Flutter中切换onDismissable事件中的收藏夹

时间:2020-09-19 10:56:33

标签: flutter dart 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,
                        ),
                      ),

Same Button通过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个文件

master_bloc

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


2 个答案:

答案 0 :(得分:0)

所以执行切换的一种方法是用一个替换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);
}

接下来,在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.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);
    }

答案 1 :(得分:0)

视频课程

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

这是onPressed的操作,但由于任何原因未反映出颜色变化

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,
                        ),
                      ),