无法在颤动的列表视图小部件中显示 phone 中的联系人姓名

Unable to display contact names from phone in a list view widget in flutter

我正在尝试使用 bloc 从联系人服务中获取联系人,并在列表视图的覆盖小部件中显示联系人姓名。您能否检查我的代码并让我知道哪里出了问题,因为它无法获取任何联系人并显示姓名。

提前感谢您抽出时间。

P.S。我添加了打印语句,但其中 none 显示了联系方式(姓名)。

文件 1: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 [];


  }


}

在您的数据服务 class 中,当您调用 getPhoneContacts() 时,您会获取联系人列表 List<Contact> contacts 但仅将其打印到控制台。

我想你想要做的是 return 它到你的 Bloc,所以你必须添加 return contacts; 并将 getPhoneContacts() 的 return 类型更改为 Future<List<Contact>>.

在您的 ContactCubit 中,您必须将 await _dataService.getPhoneContacts(); 的结果分配给一个变量并将其作为状态发出,例如:

Future getContacts() async {
    final contacts = await _dataService.getPhoneContacts();
    print(contacts.length);
    emit(contacts);
  }

然后在您的小部件中,您可以像这样使用 BlocBuilder 访问联系人:

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 ?? '');
        },
      ),
    ),
  }
)