RangeError (index): Invalid value: Valid value range is empty: 0 - Flutter Contacts_services - PullRequest
0 голосов
/ 26 мая 2020

Я новичок в флаттере и мне нужна помощь в создании моего приложения.

Когда я запускаю проект, он выдает сообщение об ошибке: RangeError (index): Invalid value: Valid value range пусто: 0 , я не могу отобразить никакие контакты, кроме одного, и это даже не первый контакт.

Пожалуйста, помогите. Спасибо.

Мой код:

import 'dart:io';
import 'package:contacts_service/contacts_service.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

void main() {
  FlutterError.onError = (FlutterErrorDetails details) {
    FlutterError.dumpErrorToConsole(details);
    if (kReleaseMode)
      exit(1);
  };
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter contacts',
      theme: ThemeData(),
      home: MyHomePage(title: 'Contacts Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  List<Contact> contacts = [];

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    getAllContacts();
  }

  getAllContacts() async{
    List<Contact> _contacts = (await ContactsService.getContacts()).toList();
    setState(() {
      contacts = _contacts;
    });
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Container(
        padding: EdgeInsets.all(20),
        child: Column(
          children: <Widget>[
            Text(
              'Phone Book',
            ),
            Expanded(
                child: 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
                      ),
                      leading: (contact.avatar != null && contact.avatar.length > 0) ?
                      CircleAvatar(backgroundImage: MemoryImage(contact.avatar),
                      ):
                      CircleAvatar(child: Text(contact.initials()),),
                    );
                  },
                )
            )
          ],
        ),
      ),
    );
  }
}

У меня есть все соответствующие зависимости, и я также указал user_permission для READ и WRITE.

Спасибо !!

1 Ответ

0 голосов
/ 26 мая 2020

Обычно, когда вы хотите сделать свой пользовательский интерфейс зависимым от данных из inte rnet во Flutter, вы обычно используете FutureBuilder, если знаете, что данные никогда не меняются. Вы также можете использовать StreamBuilder, который автоматически обновляется, когда данные из inte rnet изменяются, например, когда в список добавляется новый контакт. Попробуйте использовать один из них в своем коде.

В настоящий момент ваш код не так безопасен. Если asyn c функция getAllContacts() завершится до того, как весь виджет будет построен, приложение скроет sh, потому что вы в конечном итоге вызовете функцию setState() до того, как состояние виджета будет построено.

Вы можете сделать что-то вроде этого:

class _MyWidgetState extends State<MyWidget> {
  Future<List<Contact>> contacts;

  @override
  void initState() {
    super.initState();
    contacts = getAllContacts();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: FutureBuilder<List<Contact>>(
        future: contacts,
        builder: (BuildContext context, AsyncSnapshot<List<Contact>> snapshot) {
          if (!snapshot.hasData) {
            //Return a loadingscreen or placeholder widget
          }

          //Access the list of contacts:
          List<Contact> myContacts = snapshot.data; 

          //Return the widget
          return Container(
            padding: EdgeInsets.all(20),
            child: Column(
              children: <Widget>[
                Text(
                  'Phone Book',
                ),
                Expanded(
                    child: ListView.builder(
                      shrinkWrap: true,
                      itemCount: myContacts.length,
                      itemBuilder: (context, index){
                        Contact contact = myContacts[index];
                        return ListTile(
                          title: Text(contact.displayName),
                          subtitle: Text(
                              contact.phones.elementAt(0).value
                          ),
                          leading: (contact.avatar != null && contact.avatar.length > 0) ?
                          CircleAvatar(backgroundImage: MemoryImage(contact.avatar),
                          ):
                          CircleAvatar(child: Text(contact.initials()),),
                        );
                      },
                    )
                )
              ],
            ),
          );
        },
      ),
    );
  }
}

Но также кажется, что что-то не так, когда вы вызываете метод getAllContacts(). В строке: List<Contact> _contacts = (await ContactsService.getContacts()).toList(); кажется странным вызывать здесь метод toList(). ContactService.getContact(), вероятно, уже должен вернуть список контактов

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...