I am trying to use bloc to fetch contacts from contact service and display the contact names in an overlay widget in a list view. Can you please check my code and let me know what is wrong as it is not able to fetch any contacts and display the name.
Thank you for your time in advance.
P.S. I have added print statements but none of them are displaying the contact details(name).
File1: main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:invite_friends/contactsBloc.dart';
import 'accessContacts.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(scaffoldBackgroundColor: Colors.white),
home: BlocProvider
(create: (BuildContext context) => ContactCubit(),
child: AccessContacts()),
);
}
}
File 2: accessContacts.dart
import 'package:contacts_service/contacts_service.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:permission_handler/permission_handler.dart';
import 'contactDetails.dart';
import 'contactsBloc.dart';
class AccessContacts extends StatelessWidget {
late OverlayEntry _overlayEntry;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: Padding(
padding: const EdgeInsets.only(left: 16, top: 80),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ElevatedButton(onPressed: () {
_overlayEntry = showOverlayContacts(context);
Overlay.of(context)?.insert(_overlayEntry);
}, child: const Text('Grant permission to access contacts'),
style: ElevatedButton.styleFrom(
minimumSize: const Size(199, 41),
elevation: 5.0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0)),
shadowColor: const Color(0xFFE5E5E5),
primary: const Color(0xFFE5E5E5),
onPrimary: const Color(0xFFB13937),
textStyle: const TextStyle(fontFamily: 'Poppins',
fontSize: 14)),),
],
),
),
);
}
// check contacts permission
Future<PermissionStatus> _getPermission() async {
final PermissionStatus permission = await Permission.contacts.request();
print(permission);
return permission;
}
showOverlayContacts(BuildContext context) {
final ContactCubit _contactBloc = BlocProvider.of<ContactCubit>(context);
BlocProvider.of<ContactCubit>(context).getContacts();
TextEditingController editingController = TextEditingController();
OverlayState? overlayState = Overlay.of(context);
return OverlayEntry(builder: (context) =>
Positioned(
bottom: 350,
width: MediaQuery
.of(context)
.size
.width,
height: MediaQuery
.of(context)
.size
.height / 2,
child: Card(
elevation: 20,
child: searchContacts(editingController,_contactBloc),
),
), opaque: false);
}
Column searchContacts(TextEditingController editingController,_contactBloc) {
List<Contact> contacts;
return Column(
// mainAxisAlignment: MainAxisAlignment.start,
// crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(top: 22, left: 16, right: 16),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: const [
Text('Find contacts (upto 5) ',
style: TextStyle(fontFamily: 'Poppins',
fontSize: 14)),
Icon(Icons.cancel),
],
),
),
const Divider(
color: Colors.grey
),
Padding(
padding: const EdgeInsets.only(left: 16),
child: TextField(
onChanged: (value) {
print(value);
},
controller: editingController,
showCursor: true,
autofocus: true,
decoration: const InputDecoration(
border: InputBorder.none,
isDense: true,
suffixIcon: Padding(
padding: EdgeInsets.only(right: 16),
child: Icon(Icons.search, size: 30,),
),
suffixIconConstraints: BoxConstraints(
minWidth: 20,
minHeight: 20,
),
),
),
),
const Divider(
color: Colors.grey
),
BlocBuilder<ContactCubit, List<Contact>>(bloc: _contactBloc, builder: (BuildContext context, List<Contact> contacts){
return Expanded(
child: ListView.builder(itemCount: 3,itemBuilder: (context, index) {
Contact contact = contacts.elementAt(index);
return Text(contact.displayName ?? '');
},
),
);},)
],);
}}
File3: contactsBloc.dart
import 'package:contacts_service/contacts_service.dart';
import 'package:invite_friends/contactDetails.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:invite_friends/getContactList.dart';
import '';
class ContactCubit extends Cubit<List<Contact>> {
ContactCubit() : super([]);
final _dataService = DataService();
Future getContacts() async {
await _dataService.getPhoneContacts();
print(state.length);
// _dataService.getPhoneContacts();
emit(state);
}
}
File 4: getContactList.dart
import 'package:contacts_service/contacts_service.dart';
import 'package:permission_handler/permission_handler.dart';
import 'contactDetails.dart';
class DataService {
Future getPhoneContacts() async {
try{
Contact contact;
final PermissionStatus permissionStatus = await Permission.contacts.request();
if (permissionStatus == PermissionStatus.granted) {
// Get all contacts without thumbnail (faster)
List<Contact> contacts = await ContactsService.getContacts(withThumbnails: false);
for(contact in contacts){
print(contact.displayName);
}
} }
catch(e){
rethrow;
}
return [];
}
}
In your DataService class, when you call getPhoneContacts() you fetch the List of contacts List<Contact> contacts
but only print it to console.
I think what you want to do is return it to your Bloc, so you have to add return contacts;
and change the return type of getPhoneContacts() to Future<List<Contact>>
.
In your ContactCubit you have to assign the result of your await _dataService.getPhoneContacts();
to a variable and emit this as State, e.g.:
Future getContacts() async {
final contacts = await _dataService.getPhoneContacts();
print(contacts.length);
emit(contacts);
}
And in your widget you can then access the contact by using a BlocBuilder like this:
BlocBuilder.of<ContactCubit, List<Contact>>(
bloc: _contactBloc,
(context, contacts) {
return Expanded(
child: ListView.builder(
itemCount: contacts.length,
itemBuilder: (context, index) {
Contact contact = contacts.elementAt(index);
return Text(contact.displayName ?? '');
},
),
),
}
)