如何在Flutter中使用Bloc Pattern将小部件添加到ListView?

时间:2019-06-23 12:19:25

标签: flutter dart

我最近开始陷入扑朔迷离的Bloc模式,并学会了使用此project。 在这个项目中,有一个新增的发布功能,因此我想实现一个相同的功能。 即使我通过事件更改了Bloc的状态,也没有将Container Widget添加到ListView。我尝试并搜索了此问题,但无法确定:(

这是我的下面的代码。

这里是集团零件,

@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()-当状态为ContentsLoading()-之后,将显示一个带有消息文本的容器。到目前为止,一切都很好。 但是,当我按下添加按钮并触发AddContent()事件后,新内容没有显示。

这是控制台日志。

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

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

有人可以帮助我吗?在此先感谢:)

1 个答案:

答案 0 :(得分:0)

我解决了这个问题。

我只是在扩展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 }';
}

谢谢。