我正在创建一个聊天应用程序,在发送消息功能中,我使用bloc处理消息可能处于的不同状态(不同状态是:sent,delivered and seen),但问题是因为我使用BlocBuilder
来处理ui,所以它正在为所有发送的消息重建UI。让我给你看一个例子来了解更多,首先这里是我的小部件:
class MessageItemWidget extends StatelessWidget {
final Message message;
final Alignment alignment;
final BorderRadius borderRadius;
final TextStyle chatStyle;
final Color color;
const MessageItemWidget({
Key? key,
required this.message,
required this.alignment,
required this.borderRadius,
required this.chatStyle,
required this.color,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocBuilder<MessagesCubit, MessagesState>(
builder: (context, state) {
if (state is MessageSending) {
return Align(
alignment: alignment,
child: UnconstrainedBox(
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Container(
margin: const EdgeInsets.all(8),
padding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 10,
),
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width * 0.55,
),
decoration: BoxDecoration(
borderRadius: borderRadius,
color: color,
),
child: Text(
message.content,
style: chatStyle,
),
),
const Icon(
Icons.check,
color: Colors.grey,
size: 15,
),
],
),
),
);
} else if (state is MessageSent) {
return Align(
alignment: alignment,
child: UnconstrainedBox(
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Container(
margin: const EdgeInsets.all(8),
padding: const EdgeInsets.symmetric(
horizontal: 20,
vertical: 10,
),
constraints: BoxConstraints(
maxWidth: MediaQuery.of(context).size.width * 0.55,
),
decoration: BoxDecoration(
borderRadius: borderRadius,
color: color,
),
child: Text(
message.content,
style: chatStyle,
),
),
const Row(
children: [
Icon(
Icons.check,
color: Colors.blue,
size: 15,
),
Icon(
Icons.check,
color: Colors.blue,
size: 15,
),
],
)
],
),
),
);
} else {
return const SizedBox();
}
},
);
}
}
字符串
简而言之,它的作用是:如果消息被发送,则它在消息下显示一个检查图标,并且当消息已经被传送时,它在消息下显示两个检查图标。但是,每当发送消息时,它都会重新构建所有先前已发送消息的UI,这里是一个示例:
的数据
在上图中,所有消息都已成功传递。但每当我发送新消息时,就会发生这种情况:
的
已经发送的消息显示它们正在发送,但实际上它们之前已经发送过了,我怎么能只为特定的消息触发一个指定的块呢?
这是我的腕尺:
class MessagesCubit extends Cubit<MessagesState> {
ChatRepository chatRepository;
MessagesCubit(this.chatRepository) : super(MessagesInitial());
Future<void> getMessages(
BuildContext context, {
required UserChat client,
required UserChat supplier,
}) async {
emit(MessagesLoading());
final failureOrStreamOfMessages =
await chatRepository.getMessages(client: client, supplier: supplier);
failureOrStreamOfMessages.fold(
(failure) => emit(MessageError(mapFailureToMessage(failure, context))),
(streamOfMessages) => streamOfMessages.listen(
(messages) => emit(MessagesLoaded(messages)),
),
);
}
Future<void> sendMessage(BuildContext context, Message message) async {
emit(MessageSending());
final failureOrUnit = await chatRepository.sendMessage(message);
failureOrUnit.fold(
(failure) => emit(MessageError(mapFailureToMessage(failure, context))),
(_) => emit(MessageSent()),
);
}
}
型
以下是我的状态:
abstract class MessagesState extends Equatable {
const MessagesState();
@override
List<Object> get props => [];
}
class MessagesInitial extends MessagesState {}
// reading messages
abstract class ReadingMessagesState extends MessagesState {
const ReadingMessagesState();
}
class MessagesLoading extends ReadingMessagesState {}
class MessagesLoaded extends ReadingMessagesState {
final List<Message> messages;
const MessagesLoaded(this.messages);
@override
List<Object> get props => [messages];
}
class MessagesError extends ReadingMessagesState {
final String message;
const MessagesError(this.message);
@override
List<Object> get props => [message];
}
// writing messages
abstract class WritingMessagesState extends MessagesState {
const WritingMessagesState();
}
class MessageSending extends WritingMessagesState {}
class MessageSent extends WritingMessagesState {}
class MessageError extends WritingMessagesState {
final String message;
const MessageError(this.message);
@override
List<Object> get props => [message];
}
型
1条答案
按热度按时间j8ag8udp1#
我不确定您的
Message
模型是什么样子的,但让我们假设它有一个唯一的Id
字段。如果没有,您可以添加一个。您可以将其传递到您发出的任何WritingMessagesState
状态中。然后使用BlocBuilder
的buildWhen
功能,仅当来自小部件的消息ID与state
的消息ID匹配时才过滤重建。例如。
字符串
那么
emit
的示例如下所示型
然后将
buildWhen
添加到BlocBuilder型