我对flutter非常陌生,需要帮助来构建我的应用程序。
当我运行该项目时,它发出一个错误说。RangeError (index): Invalid value: 有效值范围为空: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()),),
);
},
)
)
],
),
),
);
}
}
我有所有适当的依赖性,并指定了用户的READ和WRITE权限。
通常情况下,当你想让你的UI依赖于数据从互联网在Flutter你典型的使用。FutureBuilder
如果你知道数据永远不会改变。你也可以使用 StreamBuilder
当互联网上的数据发生变化时,它会自动更新,例如,当一个新的联系人被添加到列表中。试着在你的代码中使用其中的一个。
目前你的代码还不是很安全。如果async函数 getAllContacts()
在构建整个widget之前就完成了,应用程序就会崩溃,因为你最终会调用一个名为 "Finihes "的函数。setState()
函数,然后再构建widget的状态。
你可以做这样的事情。
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()
可能已经返回一个联系人列表