我有一个呈现列表视图的组件,但我想知道构建它的最佳实践是什么?我应该使用来自 bloc 状态的消息列表还是应该在组件中有一个本地列表?
List<Message> messages = [];
@override
void initState() {
super.initState();
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
print("onMessage: $message");
var result = Message.fromMap(
new Map<String, dynamic>.from(message['notification']));
BlocProvider.of<MessagesBloc>(context).add(
AddMessage(message: result),
);
setState(() {
messages.add(result);
});
},
}
Widget build(BuildContext context) {
return BlocBuilder<MessagesBloc, MessagesState>(
builder: (context, state) {
if (state is Loading) {
return LoadingIndicator();
}
if (state is Finished) {
messages = state.messages;
return messages.length != 0
? _buildMessageView(messages)
: _buildEmptyMessageView();
}
});
};
我目前正在使用 Firebase 云消息传递,我的组件正在使用 MessageBloc,状态如下:
class MessagesBloc extends Bloc<MessagesEvent, MessagesState> {
final DatabaseService databaseService;
List<Message> _messages;
MessagesBloc({@required this.databaseService})
: assert(databaseService != null);
@override
MessagesState get initialState => Loading();
@override
Stream<MessagesState> mapEventToState(
MessagesEvent event,
) async* {
if (event is LoadingStarted) {
_messages = // Getting notification from local db
}
if (event is Finished) {
//
print("finished loading messages");
}
if (event is AddNotification) {
// yield Loading();
// Add a message to DB
_messages.add(event.message);
yield Finished(messages: _messages);
}
if (event is ClearMessages) {
// DELETE ALL MESSAGES FROM DB
_messages = List<Message>();
yield Finished(messages: _messages);
}
}
}
这是我的状态
abstract class MessagesState extends Equatable {
const MessagesState();
@override
List<Object> get props => [];
}
class Loading extends MessagesState {}
class Finished extends MessagesState {
final List<Message> messages;
const Finished({@required this.messages});
@override
List<Object> get props => [messages.length];
}
这是我的活动:
abstract class MessageEvent extends Equatable {
const MessageEvent();
@override
List<Object> get props => [];
}
class Refreshing extends MessageEvent {}
class LoadingStarted extends MessageEvent {}
class LoadingFinished extends MessageEvent {
final List<Message> messages;
const LoadingFinished({@required this.messages});
@override
List<Object> get props => [messages];
@override
String toString() => 'Loaded notifications: $messages}';
}
class ClearMessages extends MessageEvent {}
class AddMessage extends MessageEvent {
final Message message;
const AddMessage({@required this.message});
@override
List<Object> get props => [message];
}
如果父小部件中没有 BlocProvider,则需要创建一个 bloc 实例并将 bloc 交给 BlocBuilder。
MessageBloc _messageBloc = MessageBloc(databaseService: someDatabaseServicInstance);
...
Widget build(BuildContext context) {
return BlocBuilder<MessagesBloc, MessagesState>(
bloc: _messageBloc,
builder: (context, state) {
if (state is Loading) {
return LoadingIndicator();
}
if (state is Finished) {
messages = state.messages;
return messages.length != 0
? _buildMessageView(messages)
: _buildEmptyMessageView();
}
});
};
fcm 消息来了 -> addMessage -> BlocListener listen AddMessageComplete 事件 -> 替换状态中的消息变量.消息 (您应该添加 AddMessage 事件的状态,如 AddMessageFinished 或 AddMessageComplete(
List<Message> messages = [];
MessageBloc _messageBloc = BlocProvider.of<MessagesBloc>(context);
@override
void initState() {
super.initState();
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
print("onMessage: $message");
var result = Message.fromMap(
new Map<String, dynamic>.from(message['notification']));
// I exactly don't know it works, if not works use yours.
_messageBloc.add(
AddMessage(message: result),
);
//setState(() {
// messages.add(result);
//});
},
}
Widget build(BuildContext context) {
return BlocConsumer<MessagesBloc, MessagesState>(
listener: (context, state) {
if (state is AddCompleted) {
setState(() {
messages = state.messages;
}
}
},
builder: (context, state) {
if (state is Loading) {
return LoadingIndicator();
}
if (state is Finished) {
messages = state.messages;
return messages.length != 0
? _buildMessageView(messages)
: _buildEmptyMessageView();
}
},
}
);
}