我非常陌生,需要构建我的应用程序的帮助。
运行项目时,它会显示一条错误消息: RangeError(索引):无效值:有效值范围为空: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进行读取和写入。
谢谢!
答案 0 :(得分:1)
通常,当您希望UI依赖Flutter中来自互联网的数据时,如果您知道数据永不更改,则通常使用FutureBuilder
。您还可以使用StreamBuilder
,当来自互联网的数据发生更改时,它会自动更新。将新联系人添加到列表中时。尝试在您的代码中使用其中之一。
目前,您的代码并不安全。如果异步函数getAllContacts()
在构建整个窗口小部件之前结束,则应用程序将崩溃,因为您最终将在构建窗口小部件的状态之前调用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()
应该已经返回了联系人列表