I'm new to Flutter and I've been trying to use the package contacts_service to be able to have a list with names & numbers from your contacts. Below is the code of attempt, however "title: Text(contact.displayName)" gives me the error displayName error and "subtitle: Text(contact.phones.elementAt(0).value gives me the error elementAt error. From what I understand this is due to null safety, but I'm not quite sure where or how to check for null in my code. Do I do it inside the scaffold or before I build it? Thank you
import 'package:contacts_service/contacts_service.dart';
import 'package:flutter/material.dart';
class Contacts extends StatefulWidget {
@override
_Contacts createState() => _Contacts();
}
class _Contacts extends State<Contacts>{
List<Contact> contacts =[];
@override
void initState() {
super.initState();
getAllContacts();
}
getAllContacts() async{
List<Contact> _contacts = (await ContactsService.getContacts(withThumbnails: false)).toList();
setState(() {
contacts = _contacts;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Contact info'
),),
body: Container(
padding: EdgeInsets.all(20),
child: Column(
children: <Widget>[ Text ('test'),
ListView.builder(
shrinkWrap: true,
itemCount: contacts.length,
itemBuilder: (context, index) {
Contact contact = contacts[index];
return ListTile(
title: Text(contact.displayName),
subtitle: Text(
contact.phones.elementAt(0).value
),
);
},
)
],
),
),
);
}
}
CodePudding user response:
import 'package:contacts_service/contacts_service.dart';
import 'package:flutter/material.dart';
class Contacts extends StatefulWidget {
@override
_Contacts createState() => _Contacts();
}
class _Contacts extends State<Contacts>{
List<Contact> contacts =[];
@override
void initState() {
super.initState();
getAllContacts();
}
getAllContacts() async{
List<Contact> _contacts = (await ContactsService.getContacts(withThumbnails:
false)).toList();
setState(() {
contacts = _contacts;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Contact info'
),),
body: Container(
padding: EdgeInsets.all(20),
child: Column(
children: <Widget>[ Text ('test'),
ListView.builder(
shrinkWrap: true,
itemCount: contacts.length,
itemBuilder: (context, index) {
return ListTile(
title: Text("${contact.displayName}"),
subtitle: Text(
"${contact.phones.elementAt(0).value}"
),
);
},
)
],
),
),
);
}
}
TRY THIS
CodePudding user response:
First, I want you to refer to this documentation about Contact
class.
Its properties are all nullable. So you never know if it's null or not before you check it yourself.
If you want to set a default value in case it's a null, you can do it like this for this code.
Text(contact.displayName)
-> Text(contact.displayName??'default value')
The second code checks if contact.displayName
is null, and if it is, String literal which is 'default value'
will be returned. You can return any other default value you want.
And let's talk about the second one. If you try to call a method of a nullable object, you might as well check if it's null.
If you are sure that it can't be null logically(not programmtically), you can tell the compiler that this won't be null in runtime.
contact.phones.elementAt(0).value
-> contact.phones!.elementAt(0).value
But if there is a little bit of probability that contact.phones
could be null, you will see null check error again. Then let's set a default value like the first case.
contact.phones.elementAt(0).value
-> contact.phones?.elementAt(0)??defaultValue
In the code above, ?
after phones
works like, method calling of contact.phones
will be excecuted only when contact.phones
is not null. So, if it's null, nothing will be done, which will be null eventually. Then the same thing will be done as the first case afterward.
I hope this would be helpful.