BlocBuilder部分更新ListView

时间:2019-11-20 03:57:45

标签: flutter bloc

项目

您好,我正在尝试使用集团模式创建可由TextField过滤的列表视图

这是我的代码

bloc:

class HomeBloc extends Bloc<HomeEvent, HomeState> {

  List<Book> displayList = [];

  .... 

  @override
  HomeState get initialState => UnfilteredState();

  @override
  Stream<HomeState> mapEventToState(
    HomeEvent event,
  ) async* {

    .... 

    //handle filter by input
    if(event is FilterListByTextEvent) {

      displayList = displayList.where((book){
        return book.title.toLowerCase().contains(event.filterString.toLowerCase());
      }).toList();

      yield FilteredState();
    }

  }

}

视图

class BookList extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return BlocBuilder<HomeBloc, HomeState>(
      builder: (context, state) {
        final HomeBloc bloc = Provider.of<HomeBloc>(context);
        print(bloc.displayList);
        return ListView.builder(
          shrinkWrap: true,
          itemCount: bloc.displayList.length,
          itemBuilder: (context, index) {
            return Dismissible(
              key: UniqueKey(),
              background: Container(
                color: selectedColor,
              ),
              child: Container(
                height: 120,
                padding: const EdgeInsets.fromLTRB(20, 4, 20, 4),
                child: BookCard(
                  book: bloc.displayList[index],
                ),
              ),
              onDismissed: (DismissDirection direction) {
              },
            );
          },
        );
      },
    );
  }
}

问题

我已经阅读了有关块模式和列表视图的其他讨论,但是我在这里面临的问题有所不同。

每次调用Filter事件时,bloc都会正确生成一个新的displayList,但是,当BlocBuilder重建我的UI时,listview不会正确更新。 呈现新的过滤列表,但旧结果不会消失。看来新清单只是堆叠在旧清单之上。

为了了解发生了什么,我尝试在调用build方法之前在BlocBuilder中打印必须呈现的列表。

打印结果正确。在控制台中,我只能看到新过滤的元素,而在用户界面中,我可以看到新的和旧的元素,一个又一个。

我在这里想念什么?

谢谢

2 个答案:

答案 0 :(得分:1)

在displayList之前为加载和收益设置新状态。

if(event is FilterListByTextEvent) {
    yield LoadFilterList();
    displayList = displayList.where((book)
    {
        return 
        book.title.toLowerCase().contains(event.filterString.toLowerCase());
    }).toList();

    yield FilteredState();
}

答案 1 :(得分:0)

保留一个中间事件,例如一个ListInit,您将为其显示CircularProgressIndicator。除非您再次对其进行更新,否则BlocBuilder将停留在先前的状态。

因此在您的集团中,首先产生ListInit状态,然后执行过滤操作,然后产生FilteredState。