【问题标题】:Flutter: bloc not removing data from the listFlutter:块不从列表中删除数据
【发布时间】:2021-03-03 05:22:08
【问题描述】:

我正在尝试使用bloc 创建最喜欢的新闻列表,现在如果我想添加到最喜欢的列表中,它确实会发生,但是如果我想删除它,那么列表没有得到更新,所以它不会从用户界面。

我的集团逻辑,

class FavouriteBloc extends Bloc<FavouriteEvent, List<Articles>> {
  FavouriteBloc() : super(null);
  List<Articles> articles = [];
  @override
  Stream<List<Articles>> mapEventToState(FavouriteEvent event) async* {
    switch (event.eventType) {
      case EventType.add:
         articles.add(event.articles);
         yield articles;
        break;
      case EventType.delete:
        articles.remove(event.articles);
        yield articles;
        break;
    }
  }
}

事件类,

enum EventType {add, delete}

class FavouriteEvent{
  Articles articles;
  EventType eventType;
  FavouriteEvent.add({this.articles,this.eventType});
  FavouriteEvent.remove({this.articles,this.eventType});
}

用户界面部分,

在此屏幕中,当我添加到收藏夹时,它会显示我已添加的卡片列表,然后我使用 onTap 将其从列表中删除,但没有发生

class FavouriteScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var height = MediaQuery.of(context).size.height;
    var width = MediaQuery.of(context).size.width;
    return Scaffold(
      appBar: AppBar(),
      body: BlocBuilder<FavouriteBloc, List<Articles>>(
        buildWhen: (previous, current) {
          if(previous.length<current.length){
            return true;
          }
          return false;

        },
        builder: (context, newsList) {
          if (newsList == null) {
            return Center(
              child: Text(
                week7.Strings.noFav,
                style: Theme.of(context).textTheme.headline6,
              ),
            );
          }
          return ListView.builder(
              itemCount: newsList.length,
              shrinkWrap: true,
              itemBuilder: (context, index) {
                return GestureDetector(
                  onTap: () { 
                    BlocProvider.of<FavouriteBloc>(context).add(  //<--- this is how I'm trying to remove
                        FavouriteEvent.remove(
                            articles: Articles(
                                urlToImage: newsList[index].urlToImage,
                                title: newsList[index].title,
                                author: newsList[index].author
                            ),
                            eventType: EventType.delete));
                  },
                  child: Card(...),
                );
              });
        },
      ),
    );
  }
}

模型类,

@JsonSerializable()
class Articles {
  Source source;
  String author;
  String title;
  String description;
  String url;
  String urlToImage;
  DateTime publishedAt;
  String content;
  Articles({
    this.source,
    this.author,
    this.title,
    this.description,
    this.url,
    this.urlToImage,
    this.publishedAt,
    this.content,
  });

  factory Articles.fromJson(Map<String, dynamic> json) =>
      _$ArticlesFromJson(json);
}

那么谁能告诉我我在这里做错了什么?

【问题讨论】:

  • 你能分享模型类吗
  • @gowthamanC 好的,我已经在问题中添加了我的模型类

标签: flutter dart flutter-bloc


【解决方案1】:
hi bro add this lib 
https://pub.dev/packages/equatable 

@JsonSerializable()
class Articles  extends Equatable{
  Source source;
  String author;
  String title;
  String description;
  String url;
  String urlToImage;
  DateTime publishedAt;
  String content;
  Articles({
    this.source,
    this.author,
    this.title,
    this.description,
    this.url,
    this.urlToImage,
    this.publishedAt,
    this.content,
  });

 @override
  List<Object> get props => [name];//  depending on which field you want to remove the list item, replace "name" with your field.

  factory Articles.fromJson(Map<String, dynamic> json) =>
      _$ArticlesFromJson(json);
}

【讨论】:

    【解决方案2】:

    Dart 比较两个对象是否是同一个实例。您需要覆盖== 运算符或使用equatable 之类的库。

    您需要做的第一件事是删除buildWhen。现在它只会在您添加项目时更新(重建)而不是在您删除它们时。

            buildWhen: (previous, current) {
              if(previous.length<current.length){
                return true;
              }
              return false;
    
            },
    

    使用 State 类来表示状态,因为列表始终相同,不会重新构建。之后调整您的小部件代码以使用state.articles

    class FavouriteState {
     final List<Articles> articles;
     FavouriteState(this.artticles);
    }
    
    class FavouriteBloc extends Bloc<FavouriteEvent, FavouriteState> {
      FavouriteBloc() : super(null);
      List<Articles> _articles = [];
      @override
      Stream<FavouriteState> mapEventToState(FavouriteEvent event) async* {
        switch (event.eventType) {
          case EventType.add:
             _articles.add(event.articles);
             yield FavouriteState(_articles);
            break;
          case EventType.delete:
            _articles.remove(event.articles);
            yield FavouriteState(_articles);
            break;
        }
      }
    }
    

    比较urlToImagetitleauthor 的示例

    @JsonSerializable()
    class Articles {
      Source source;
      String author;
      String title;
      String description;
      String url;
      String urlToImage;
      DateTime publishedAt;
      String content;
      Articles({
        this.source,
        this.author,
        this.title,
        this.description,
        this.url,
        this.urlToImage,
        this.publishedAt,
        this.content,
      });
    
        @override
      bool operator ==(Object other) =>
          identical(this, other) ||
          other is Articles && runtimeType == other.runtimeType && urlToImage == other.urlToImage &&
          title == other.title && author == other.author;
    
      @override
      int get hashCode => urlToImage.hashCode ^ title.hashCode ^ author.hashCode;
    
      factory Articles.fromJson(Map<String, dynamic> json) =>
          _$ArticlesFromJson(json);
    }
    

    使用Equatable 包的示例

    @JsonSerializable()
    class Articles  extends Equatable{
      Source source;
      String author;
      String title;
      String description;
      String url;
      String urlToImage;
      DateTime publishedAt;
      String content;
      Articles({
        this.source,
        this.author,
        this.title,
        this.description,
        this.url,
        this.urlToImage,
        this.publishedAt,
        this.content,
      });
    
     @override
      List<Object> get props => [author, title, description, url, urlToImage, content];
    
      factory Articles.fromJson(Map<String, dynamic> json) =>
          _$ArticlesFromJson(json);
    }
    

    【讨论】:

    • 好的,但它会在状态更改后重建,所以我在buildWhen 的情况是正确的还是我需要做其他事情
    • 状态变化时重建是正常的。你的条件是当列表的大小发生变化时,重建。从列表中添加或删除项目将触发重建,这是正常行为。如果它不重建,那么您将看不到更改的文章。
    • tbh 您需要删除 buildWhen。您希望每次在列表中添加或删除项目时触发重建。在那种情况下没有意义。现在它只会在您添加项目时重建,而不是在您删除它们时。
    • sry 我忘了'not',它不会重建
    • 如果您删除项目,它将不会重建。正确的?那来自buildWhen。去掉buildWhen就可以了。
    猜你喜欢
    • 1970-01-01
    • 2021-05-03
    • 1970-01-01
    • 1970-01-01
    • 2021-11-22
    • 1970-01-01
    • 2018-04-13
    • 2021-02-04
    • 2021-11-22
    相关资源
    最近更新 更多