I'm following a tutorial series that creates a messaging app in flutter. It's slightly outdated but I'm trying to follow along with the most updated version.
I'm getting the following error:
The argument type 'Object?' can't be assigned to the parameter type 'String'.
For this code snippet: (everything after tryParse is underlined in red).
return chatsWithLatestMessage.map<Chat>((row) {
final int? unread = int.tryParse(chatsWithUnreadMessages.firstWhere(
(ele) => row['chat_id'] == ele['chat_id'],
orElse: () => {'unread': 0})['unread']);
I tried adding .toString()
at the end, but then I get more errors because it's supposed to be int:
Use a non-nullable type for a final variable initialized with a non-nullable value.dartunnecessary_nullable_for_final_variable_declarations
A value of type 'String' can't be assigned to a variable of type 'int?'.
Try changing the type of the variable, or casting the right-hand type to 'int?'.dartinvalid_assignment
The argument type 'Object?' can't be assigned to the parameter type 'String'.
I also tried adding .toString()
in a few other places in the code, but then got errors saying that what came after .toString()
could not be used with Strings.
I think there's something more going on here with all the types. Any ideas what I can do? I'm a total beginner so odds are, the fix is something very basic that I'm just not seeing. I can edit to include more code & files upon request.
This is the whole function that the code snippet lives in:
@override
Future<List<Chat>> findAllChats() {
return _db.transaction((txn) async {
final chatsWithLatestMessage = await txn.rawQuery(''' SELECT messages.* FROM
(SELECT
chat_id, MAX(created_at) AS created_at
FROM messages
GROUP BY chat_id
) AS latest_messages
INNER JOIN messages
ON messages.chat_id = latest_messages.chat_id
AND messages.created_at = latest_messages.created_at
''');
final chatsWithUnreadMessages =
await txn.rawQuery('''SELECT chat_id, count(*) as unread
FROM messages
WHERE receipt = ?
GROUP BY chat_id
''', ['delivered']);
return chatsWithLatestMessage.map<Chat>((row) {
final int? unread = int.tryParse(chatsWithUnreadMessages.firstWhere(
(ele) => row['chat_id'] == ele['chat_id'],
orElse: () => {'unread': 0})['unread']).toString();
final chat = Chat.fromMap(row);
chat.unread = unread!;
chat.mostRecent = LocalMessage.fromMap(row);
return chat;
}).toList();
});
}
Edit: here is the chat model:
import 'package:rethink_chat/models/local_message.dart';
class Chat {
late String id; // added late
int unread = 0;
List<LocalMessage>? messages = [];
LocalMessage? mostRecent; // added late
Chat(this.id, {this.messages, this.mostRecent});
toMap() => {'id': id};
factory Chat.fromMap(Map<String, dynamic> json) => Chat(json['id']);
}
CodePudding user response:
The first bug, is that you are declaring the value final int? unread...
and assign it to value that will never be a null
, and it will never be null because you are using the orElse
part,
To solve this, you can do one of the following:
1- declare your unread
value as a final int unread
2- or remove the orElse
part and set your chat.unread to chat.unread = unread ?? 0;
The second bug, is that you've declared the unread
value as an int?
but you are assigning it to a string value by writing orElse: () => {'unread': 0})['unread']).toString()
the .toString()
and this must be removed for either of the solutions above
---- Update:
final chatsWithUnreadMessages =
await txn.rawQuery('''SELECT chat_id, count(*) as unread
FROM messages
WHERE receipt = ?
GROUP BY chat_id
''', ['delivered']);
The above code will return for you a List<Map<String, dynamic>>, Ex:
chatsWithUnreadMessages = [
{
"chat_id": 1,
"unread": 3
},
{
"chat_id": 1,
"unread": 3
}
]
and after mapping them, the firstWhere
will return for you a whole record of the list, so if it found a record that mets row['chat_id'] == ele['chat_id']
it will return the whole row
and the whole row will be something like:
{
"chat_id": 1,
"unread": 3
}
and that is an Object
to flutter and it is not String so it cannot be parse-able!
//Your code
return chatsWithLatestMessage.map<Chat>((row) {
final int? unread = int.tryParse(chatsWithUnreadMessages.firstWhere(
(ele) => row['chat_id'] == ele['chat_id'],
orElse: () => {'unread': 0})['unread']).toString();
....
//Updated code
return chatsWithLatestMessage.map<Chat>((row) {
final int? unread = int.tryParse(chatsWithUnreadMessages
.firstWhere((ele) => row['chat_id'] == ele['chat_id'],
orElse: () => {'unread': 0})['unread']
.toString());
...
});
//What I done is I entered the ".toString()" inside the int.tryParse() parenthesis
I believe that this would solve the problem