首页 > 解决方案 > 如何在颤动中使用 Bloc 模式将小部件添加到 ListView?

问题描述

我最近开始深入研究 Flutter 中的 Bloc Pattern,并学习了如何使用这个项目。在这个项目中,有一个添加帖子功能,所以我想实现一个类似的功能。即使我通过事件更改了 Bloc 的状态,它也没有将 Container Widget 添加到 ListView。我试过搜索这个问题,但我不知道:(

下面是我的代码。

这是 Bloc 零件,

@immutable
abstract class ContentsState extends Equatable {
  ContentsState([List props = const []]) : super(props);
}

class ContentsLoading extends ContentsState {
  @override
  String toString() => 'ContentsLoading';
}

class ContentsLoaded extends ContentsState {
  final List<Content> contents;

  ContentsLoaded(this.contents);

  @override
  String toString() => 'ContentsLoaded { contents: $contents }';
}
@immutable
abstract class ContentsEvent extends Equatable {
  ContentsEvent([List props = const []]) : super(props);
}

class LoadContents extends ContentsEvent {
  @override
  String toString() => 'LoadContents';
}

class AddContent extends ContentsEvent {
  final Content content;

  AddContent(this.content) : super([content]);

  @override
  String toString() => 'AddContent { content: $content }';
}
class ContentsBloc extends Bloc<ContentsEvent, ContentsState> {
  @override
  ContentsState get initialState => ContentsLoading();

  @override
  Stream<ContentsState> mapEventToState(ContentsEvent event) async* {
    if (event is LoadContents) {
      yield* _mapLoadContentsToState();
    } else if (event is AddContent) {
      yield* _mapAddContentToState(event);
    }
  }

  Stream<ContentsState> _mapLoadContentsToState() async* {
    final List<Content> contents = [Content('message')];
    yield ContentsLoaded(contents);
  }

  Stream<ContentsState> _mapAddContentToState(AddContent event) async* {
    if (currentState is ContentsLoaded) {
      final List<Content> updateContents =
          List.from((currentState as ContentsLoaded).contents)
            ..add(event.content);
      // Output update contents
      print('update contents : $updateContents');
      yield ContentsLoaded(updateContents);
    }
  }
}

和演示部分,

class AddPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      builder: (context) => ContentsBloc()..dispatch(LoadContents()),
      child: Column(
        children: <Widget>[
          AddBody(),
          InputArea(),
        ],
      ),
    );
  }
}

class AddBody extends StatelessWidget {
  AddBody({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final contentsBloc = BlocProvider.of<ContentsBloc>(context);

    return BlocBuilder(
      bloc: contentsBloc,
      builder: (
        BuildContext context,
        ContentsState state,
      ) {
        if (state is ContentsLoading) {
          return Center(child: CircularProgressIndicator());
        } else if (state is ContentsLoaded) {
          final contents = state.contents;
          return Expanded(
            child: ListView.builder(
              itemCount: contents.length,
              itemBuilder: (context, index) {
                final content = contents[index];
                return ContentItem(content: content);
              },
            ),
          );
        }
      },
    );
  }
}

class ContentItem extends StatelessWidget {
  final Content content;

  ContentItem({
    Key key,
    this.content,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      key: Key('__Content__${content.message}__'),
      child: Column(
        children: <Widget>[
          Text('Message Here'),
          Text(content.message.toString()),
        ],
      ),
    );
  }
}

~~ in InputArea. There is a TextEditingController and TextField.
onTap: () => contentsBloc.dispatch(AddContent(Content(_controller.text))),
~~

最后,这是我的 Content 类

@immutable
class Content extends Equatable {
  final String message;

  Content(this.message);

  @override
  String toString() => 'Content { message: $message }';
}

当我运行此代码时,我可以看到 CircleProgressIndicator() -When State is ContentsLoading()- 之后,会显示一个带有消息文本的容器。到目前为止,一切都很好。但是在我按下添加按钮并触发 AddContent() 事件后,新内容不会出现。

这是一个控制台日志。

AddContent { content: Content { message: new message } }
update contents : [Content { message: message }, Content { message: new message }]

我想添加容器,但它不起作用。

谁能帮我?提前致谢:)

标签: flutterdart

解决方案


我解决了这个问题。

我只是在扩展 ContentsState 的 Bloc 的 ContentsLoaded 类中添加了这一行。

class ContentsLoaded extends ContentsState {
  final List<Content> contents;

  // just add this line below.
  ContentsLoaded([this.contents = const []]) : super([contents]);

  @override
  String toString() => 'ContentsLoaded { contents: $contents }';
}

谢谢。


推荐阅读