我有一个存储 ChatRoom 对象的盒子
@HiveType(typeId: 2)
class ChatRoom {
@HiveField(1)
String name;
@HiveField(2)
List<ChatMessage> chatmessage;
ChatRoom({
required this.name,
required this.chatmessage,
});
}
@HiveType(typeId: 3)
class ChatMessage {
@HiveField(3)
String name;
@HiveField(4)
String message;
@HiveField(5)
String time;
@HiveField(6)
bool isSender;
@HiveField(7)
String deliverStatus;
ChatMessage(
{required this.name,
required this.message,
required this.time,
required this.isSender,
required this.deliverStatus});
}
我使用 ValueListenableBuilder 成功监听了它们的创建和修改
return ValueListenableBuilder(
valueListenable: Hive.box<ChatRoom>('ChatRooms').listenable(),
builder: (context, Box<ChatRoom> _chatStorageBox, _) {
return ListView.separated(
separatorBuilder: (context, index) => const Divider(
color: Colors.white,
),
itemCount: _chatStorageBox.values.length,
itemBuilder: (context, index) {
final chatRoom = _chatStorageBox.getAt(index) as ChatRoom;
String message = chatRoom.chatmessage.last.message;
bool isSender = chatRoom.chatmessage.last.isSender;
String time = chatRoom.chatmessage.last.time;
List<ChatMessage> listOfChatMessages = chatRoom.chatmessage;
final chatName = chatRoom.name;
return InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ChatScreen(
listOfmessages: listOfChatMessages,
userNumber: chatName,
server:
'',
)));
},
child: ConversationWidget(
isSender: isSender,
name: chatName,
messageText: message,
time: time),
);
},
);
});
class ChatScreen extends StatefulWidget {
ChatScreen(
{required this.userNumber,
required this.server,
required this.listOfmessages,
Key? key})
: super(key: key);
String userNumber;
String server;
List<ChatMessage> listOfmessages;
@override
State<ChatScreen> createState() => _ChatScreenState();
}
class _ChatScreenState extends State<ChatScreen> {
final _textController = TextEditingController();
final String toNumber = 'remoteAddress';
final String message = 'message';
List<ChatMessage> msgList = []; // ??
late final ValueNotifier<List<ChatMessage>> listenListOfmessages;
@override
void initState() {
msgList = widget.listOfmessages;
listenListOfmessages = ValueNotifier<List<ChatMessage>>(msgList);
super.initState();
}
@override
void dispose() {
_textController.dispose();
super.dispose();
}
static Box<ChatRoom> box = Hive.box<ChatRoom>('ChatRooms');
@override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
///////////////////////////////////////////////////
return Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(
actions: [
IconButton(
onPressed: () {
print('add contact');
},
icon: Image.asset('assets/images/ic_add_contact_holo_dark.png'))
],
title: const Text('Tel'),
// backgroundColor: Constants.kIconColorLightTheme,
backgroundColor: Colors.grey[900],
),
body: ChangeNotifierProvider(
create: (_) => MessageService(),
child: Column(
children: [
Container(
color: Colors.grey[800],
child: Row(
children: [
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(left: 10, bottom: 5),
child: Text(
widget.userNumber,
style: customTextStyle(18),
),
),
Padding(
padding: EdgeInsets.only(left: width / 39.2),
child: Text(
'sip: ' + widget.userNumber + '@' + widget.server,
style: const TextStyle(color: Colors.white),
),
),
],
),
const Spacer(),
Padding(
padding: const EdgeInsets.only(bottom: 5),
child: authStateWidget(
context,
'7221',
widget.server,
'',
width,
height),
),
],
),
),
ValueListenableBuilder(
valueListenable: listenListOfmessages,
builder: (context, List<ChatMessage> _chatRoomBox, _) {
return Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: listenListOfmessages.value.length,
itemBuilder: (context, int index) {
final String chatMessage =
listenListOfmessages.value[index].message;
return ListTile(
leading: Text(chatMessage),
);
},
),
);
}),
IconButton(
onPressed: () {
Navigator.of(context).pop();
},
icon: const Icon(Icons.arrow_back)),
Container(
decoration: BoxDecoration(color: Colors.grey[900]),
child: Padding(
padding: const EdgeInsets.only(left: 5, right: 5),
child: Row(
children: [
SizedBox(
width: width / 1.35,
child: Padding(
padding: EdgeInsets.only(
bottom: height / 40.1, left: width / 39.2),
child: TextField(
style: const TextStyle(color: Colors.white),
controller: _textController,
decoration: const InputDecoration(
hintText: 'Type to compose',
hintStyle: TextStyle(
fontSize: 14.0, color: Colors.white),
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.white),
borderRadius: BorderRadius.only(
bottomRight: Radius.zero)),
),
),
),
),
SizedBox(
width: width / 39.2,
),
Expanded(
child: SizedBox(
width: width / 4.9,
child: ElevatedButton(
// style: ElevatedButton.styleFrom(
// backgroundColor: Colors.grey[800]),
onPressed: () async {
MessageService().writeOutcomingMessage(
ChatMessage(
name: widget.userNumber,
message: _textController.text,
time: DateFormat('yyyy-MM-dd – kk:mm')
.format(DateTime.now()),
isSender: true,
deliverStatus: 'sending..'),
<String, String>{
toNumber: widget.userNumber,
message: _textController.text,
});
_textController.clear();
},
child: const Text(
'Send',
style:
TextStyle(fontSize: 16, color: Colors.white),
),
),
),
),
],
),
),
),
],
),
));
}
我想监听聊天消息列表中的更改,并在列表中出现新消息时调用 СhatScreen 重建。 我尝试在 СhatScreen 中创建另一个 ValueListenableBuilder 并仅监听列表中的更改,但我不知道如何访问此框字段。这里正确的方法是什么?
我有一个类似的实现。我已更改变量名称以匹配您自己的变量名称。看看吧
class ChatScreen extends StatelessWidget {
final String chatRoomId;
ChatScreen({super.key, required this.chatRoomId});
@override
Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable: Hive.box<ChatRoom>('ChatRooms').listenable(keys: [chatRoomId]),
builder: (context, box, _) {
final chat = box.values.firstWhere((element) => element.id == chatRoomId);
return Scaffold(
appBar: AppBar(
leading: BackButton(
onPressed: () => Get.back(),
),
title: Text(chat.convoName)),
body: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: chat.messages.length,
itemBuilder: (context, index) {
final message = chat.messages[index];
return MessageWidget(message: message);
},
),
),
MessageInputWidget(
chatId: chatId,
)
],
),
);
});
}
}