У меня есть два экрана: один, на котором пользователь может общаться с конкретным человеком, и второй экран, где он может видеть список всех чатов.
Цель состоит в том, чтобы отобразить последнее сообщение на второй экран. Это делается следующим образом:
- Пользователь отправляет / получает новое сообщение?
- Обновить базу данных
- Blo C отправляет новый поток данных по получение самых новых данных.
Проблема в том, что построитель потока не слушает новые данные (не знаю почему). Насколько мне известно, Blo C отправляет новый поток данных, когда пользователь отправляет сообщение, он просто не отображает его повторно в списке.
Вот сокращенная версия код:
class ChatScreen extends StatelessWidget {
final ContactsBloc _contactsBloc = ContactsBloc();
@override()
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
Navigator.pop(context, true);
},
),
body: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Expanded(
child: TextField(
controller: messageTextController,
onChanged: (value) {
message = value;
},
decoration: kMessageTextFieldDecoration,
),
),
FlatButton(
onPressed: () async {
//update remote and local databases
await _contactsBloc.updateContact(
{'last_message': utf8.decode(base64.decode(message))},
'conversation_id = ?',
[conversationId]);
},
child: Text(
'Send',
style: kSendButtonTextStyle,
),
),
],
),
Экран чатов:
class ChatsScreen extends StatefulWidget {
static const id = 'chats';
@override
_ChatsScreenState createState() => _ChatsScreenState();
}
class _ChatsScreenState extends State<ChatsScreen> {
final ContactsBloc _contactsBloc = ContactsBloc();
Iterable<Contact> contacts;
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Chats'),
body: Container(
child: StreamBuilder(
stream: _contactsBloc.contacts,
builder: (context, results) {
print('New stream: $results');
if (!results.hasData) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: CircularProgressIndicator(),
),
],
);
} else {
List contacts = results.data;
contacts = contacts
.where((element) => element.lastMessage != null)
.toList();
if (contacts.length > 0) {
return ListView.builder(
itemCount: contacts.length,
itemBuilder: (context, index) {
ContactModel contact = contacts[index];
return ChatItem(
name: contact.name,
message: contact.lastMessage,
profilePicture: contact.profilePictureUrl,
lastSeen: contact.lastSeen,
user: currentUser,
toUser: contact.uid,
conversationId: contact.conversationId,
);
},
);
}
return Container();
}
},
)),
);
}
}
Контакт Blo C:
class ContactsBloc {
ContactsBloc() {
getAllContacts();
}
final _contactsController = StreamController<List<ContactModel>>.broadcast();
Stream<List<ContactModel>> get contacts => _contactsController.stream;
_dispose() {
_contactsController.close();
}
getAllContacts() async {
List<ContactModel> contacts = await DatabaseProvider.db.getAllContacts();
_contactsController.sink.add(contacts);
}
updateContact(var update, String where, List whereArgs) async {
await DatabaseProvider.db.updateContact(update, where, whereArgs);
getAllContacts();
}
}