flutter - contacts_service.dart 仅更新至白色数据
问题描述
我正在使用contact_service.dart 来更新电话联系人,如下所示:
1. 我确保我已获得所有许可证。
2. 我得到一个带有我想要编辑的联系人的 Iterable。
Iterable <Contact> johns = await ContactsService.getContacts (query: "john");
3.我编辑数据改变
johns .first.givenName = expect "jhon2"
4.我做更新
await ContactsService.updateContact (jhons.first);
问题是当我检查电话簿中的联系人时。联系人只有空白数据,似乎程序删除了所有联系人信息,我不知道为什么。
有谁能够帮我?
任何曾经使用过“contact_service”插件的人都可以给我一个联系人更新示例吗?
解决方案
您可以下载https://github.com/lukasgit/flutter_contacts/tree/master/example
并替换contacts_list_page.dart
为以下完整代码
单击更新图标将调用_updateTest
更新john
的相关数据您可以在
代码片段
下面看到工作演示
return Scaffold(
appBar: AppBar(
title: Text(
'Contacts Plugin Example',
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.create),
onPressed: _openContactForm,
),
IconButton(
icon: Icon(Icons.memory),
onPressed: _updateTest,
)
],
_updateTest() async {
Iterable<Contact> johns = await ContactsService.getContacts(query: "john");
if(johns.length > 0) {
var firstConatct = johns.first;
print(firstConatct.middleName);
firstConatct.givenName = "jhon2";
firstConatct.middleName = "hi";
firstConatct.phones = [Item(label: "phone", value: "1234567")];
await ContactsService.updateContact(firstConatct);
refreshContacts();
}
}
工作演示
电话
contacts_list_page.dart
完整代码
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:contacts_service_example/main.dart';
import 'package:contacts_service/contacts_service.dart';
import 'package:intl/intl.dart';
class ContactListPage extends StatefulWidget {
@override
_ContactListPageState createState() => _ContactListPageState();
}
class _ContactListPageState extends State<ContactListPage> {
List<Contact> _contacts;
@override
void initState() {
super.initState();
refreshContacts();
}
Future<void> refreshContacts() async {
// Load without thumbnails initially.
var contacts = (await ContactsService.getContacts(
withThumbnails: false, iOSLocalizedLabels: iOSLocalizedLabels))
.toList();
// var contacts = (await ContactsService.getContactsForPhone("8554964652"))
// .toList();
setState(() {
_contacts = contacts;
});
// Lazy load thumbnails after rendering initial contacts.
for (final contact in contacts) {
ContactsService.getAvatar(contact).then((avatar) {
if (avatar == null) return; // Don't redraw if no change.
setState(() => contact.avatar = avatar);
});
}
}
void updateContact() async {
Contact ninja = _contacts
.toList()
.firstWhere((contact) => contact.familyName.startsWith("Ninja"));
ninja.avatar = null;
await ContactsService.updateContact(ninja);
refreshContacts();
}
_openContactForm() async {
try {
var contact = await ContactsService.openContactForm(
iOSLocalizedLabels: iOSLocalizedLabels);
refreshContacts();
} on FormOperationException catch (e) {
switch (e.errorCode) {
case FormOperationErrorCode.FORM_OPERATION_CANCELED:
case FormOperationErrorCode.FORM_COULD_NOT_BE_OPEN:
case FormOperationErrorCode.FORM_OPERATION_UNKNOWN_ERROR:
default:
print(e.errorCode);
}
}
}
_updateTest() async {
Iterable<Contact> johns = await ContactsService.getContacts(query: "john");
if (johns.length > 0) {
var firstConatct = johns.first;
print(firstConatct.middleName);
firstConatct.givenName = "jhon2";
firstConatct.middleName = "hi";
firstConatct.phones = [Item(label: "phone", value: "1234567")];
await ContactsService.updateContact(firstConatct);
refreshContacts();
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
'Contacts Plugin Example',
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.create),
onPressed: _openContactForm,
),
IconButton(
icon: Icon(Icons.memory),
onPressed: _updateTest,
)
],
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
Navigator.of(context).pushNamed("/add").then((_) {
refreshContacts();
});
},
),
body: SafeArea(
child: _contacts != null
? ListView.builder(
itemCount: _contacts?.length ?? 0,
itemBuilder: (BuildContext context, int index) {
Contact c = _contacts?.elementAt(index);
return ListTile(
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (BuildContext context) => ContactDetailsPage(
c,
onContactDeviceSave:
contactOnDeviceHasBeenUpdated,
)));
},
leading: (c.avatar != null && c.avatar.length > 0)
? CircleAvatar(backgroundImage: MemoryImage(c.avatar))
: CircleAvatar(child: Text(c.initials())),
title: Text(c.displayName ?? ""),
);
},
)
: Center(
child: CircularProgressIndicator(),
),
),
);
}
void contactOnDeviceHasBeenUpdated(Contact contact) {
this.setState(() {
var id = _contacts.indexWhere((c) => c.identifier == contact.identifier);
_contacts[id] = contact;
});
}
}
class ContactDetailsPage extends StatelessWidget {
ContactDetailsPage(this._contact, {this.onContactDeviceSave});
final Contact _contact;
final Function(Contact) onContactDeviceSave;
_openExistingContactOnDevice(BuildContext context) async {
try {
var contact = await ContactsService.openExistingContact(_contact,
iOSLocalizedLabels: iOSLocalizedLabels);
if (onContactDeviceSave != null) {
onContactDeviceSave(contact);
}
Navigator.of(context).pop();
} on FormOperationException catch (e) {
switch (e.errorCode) {
case FormOperationErrorCode.FORM_OPERATION_CANCELED:
case FormOperationErrorCode.FORM_COULD_NOT_BE_OPEN:
case FormOperationErrorCode.FORM_OPERATION_UNKNOWN_ERROR:
default:
print(e.toString());
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(_contact.displayName ?? ""),
actions: <Widget>[
// IconButton(
// icon: Icon(Icons.share),
// onPressed: () => shareVCFCard(context, contact: _contact),
// ),
IconButton(
icon: Icon(Icons.delete),
onPressed: () => ContactsService.deleteContact(_contact),
),
IconButton(
icon: Icon(Icons.update),
onPressed: () => Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => UpdateContactsPage(
contact: _contact,
),
),
),
),
IconButton(
icon: Icon(Icons.edit),
onPressed: () => _openExistingContactOnDevice(context)),
],
),
body: SafeArea(
child: ListView(
children: <Widget>[
ListTile(
title: Text("Name"),
trailing: Text(_contact.givenName ?? ""),
),
ListTile(
title: Text("Middle name"),
trailing: Text(_contact.middleName ?? ""),
),
ListTile(
title: Text("Family name"),
trailing: Text(_contact.familyName ?? ""),
),
ListTile(
title: Text("Prefix"),
trailing: Text(_contact.prefix ?? ""),
),
ListTile(
title: Text("Suffix"),
trailing: Text(_contact.suffix ?? ""),
),
ListTile(
title: Text("Birthday"),
trailing: Text(_contact.birthday != null
? DateFormat('dd-MM-yyyy').format(_contact.birthday)
: ""),
),
ListTile(
title: Text("Company"),
trailing: Text(_contact.company ?? ""),
),
ListTile(
title: Text("Job"),
trailing: Text(_contact.jobTitle ?? ""),
),
ListTile(
title: Text("Account Type"),
trailing: Text((_contact.androidAccountType != null)
? _contact.androidAccountType.toString()
: ""),
),
AddressesTile(_contact.postalAddresses),
ItemsTile("Phones", _contact.phones),
ItemsTile("Emails", _contact.emails)
],
),
),
);
}
}
class AddressesTile extends StatelessWidget {
AddressesTile(this._addresses);
final Iterable<PostalAddress> _addresses;
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
ListTile(title: Text("Addresses")),
Column(
children: _addresses
.map((a) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
children: <Widget>[
ListTile(
title: Text("Street"),
trailing: Text(a.street ?? ""),
),
ListTile(
title: Text("Postcode"),
trailing: Text(a.postcode ?? ""),
),
ListTile(
title: Text("City"),
trailing: Text(a.city ?? ""),
),
ListTile(
title: Text("Region"),
trailing: Text(a.region ?? ""),
),
ListTile(
title: Text("Country"),
trailing: Text(a.country ?? ""),
),
],
),
))
.toList(),
),
],
);
}
}
class ItemsTile extends StatelessWidget {
ItemsTile(this._title, this._items);
final Iterable<Item> _items;
final String _title;
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
ListTile(title: Text(_title)),
Column(
children: _items
.map(
(i) => Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: ListTile(
title: Text(i.label ?? ""),
trailing: Text(i.value ?? ""),
),
),
)
.toList(),
),
],
);
}
}
class AddContactPage extends StatefulWidget {
@override
State<StatefulWidget> createState() => _AddContactPageState();
}
class _AddContactPageState extends State<AddContactPage> {
Contact contact = Contact();
PostalAddress address = PostalAddress(label: "Home");
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Add a contact"),
actions: <Widget>[
FlatButton(
onPressed: () {
_formKey.currentState.save();
contact.postalAddresses = [address];
ContactsService.addContact(contact);
Navigator.of(context).pop();
},
child: Icon(Icons.save, color: Colors.white),
)
],
),
body: Container(
padding: EdgeInsets.all(12.0),
child: Form(
key: _formKey,
child: ListView(
children: <Widget>[
TextFormField(
decoration: const InputDecoration(labelText: 'First name'),
onSaved: (v) => contact.givenName = v,
),
TextFormField(
decoration: const InputDecoration(labelText: 'Middle name'),
onSaved: (v) => contact.middleName = v,
),
TextFormField(
decoration: const InputDecoration(labelText: 'Last name'),
onSaved: (v) => contact.familyName = v,
),
TextFormField(
decoration: const InputDecoration(labelText: 'Prefix'),
onSaved: (v) => contact.prefix = v,
),
TextFormField(
decoration: const InputDecoration(labelText: 'Suffix'),
onSaved: (v) => contact.suffix = v,
),
TextFormField(
decoration: const InputDecoration(labelText: 'Phone'),
onSaved: (v) =>
contact.phones = [Item(label: "mobile", value: v)],
keyboardType: TextInputType.phone,
),
TextFormField(
decoration: const InputDecoration(labelText: 'E-mail'),
onSaved: (v) =>
contact.emails = [Item(label: "work", value: v)],
keyboardType: TextInputType.emailAddress,
),
TextFormField(
decoration: const InputDecoration(labelText: 'Company'),
onSaved: (v) => contact.company = v,
),
TextFormField(
decoration: const InputDecoration(labelText: 'Job'),
onSaved: (v) => contact.jobTitle = v,
),
TextFormField(
decoration: const InputDecoration(labelText: 'Street'),
onSaved: (v) => address.street = v,
),
TextFormField(
decoration: const InputDecoration(labelText: 'City'),
onSaved: (v) => address.city = v,
),
TextFormField(
decoration: const InputDecoration(labelText: 'Region'),
onSaved: (v) => address.region = v,
),
TextFormField(
decoration: const InputDecoration(labelText: 'Postal code'),
onSaved: (v) => address.postcode = v,
),
TextFormField(
decoration: const InputDecoration(labelText: 'Country'),
onSaved: (v) => address.country = v,
),
],
),
),
),
);
}
}
class UpdateContactsPage extends StatefulWidget {
UpdateContactsPage({@required this.contact});
final Contact contact;
@override
_UpdateContactsPageState createState() => _UpdateContactsPageState();
}
class _UpdateContactsPageState extends State<UpdateContactsPage> {
Contact contact;
PostalAddress address = PostalAddress(label: "Home");
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
@override
void initState() {
super.initState();
contact = widget.contact;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Update Contact"),
actions: <Widget>[
IconButton(
icon: Icon(
Icons.save,
color: Colors.white,
),
onPressed: () async {
_formKey.currentState.save();
contact.postalAddresses = [address];
await ContactsService.updateContact(contact);
Navigator.of(context).pushReplacement(
MaterialPageRoute(builder: (context) => ContactListPage()));
},
),
],
),
body: Container(
padding: EdgeInsets.all(12.0),
child: Form(
key: _formKey,
child: ListView(
children: <Widget>[
TextFormField(
initialValue: contact.givenName ?? "",
decoration: const InputDecoration(labelText: 'First name'),
onSaved: (v) => contact.givenName = v,
),
TextFormField(
initialValue: contact.middleName ?? "",
decoration: const InputDecoration(labelText: 'Middle name'),
onSaved: (v) => contact.middleName = v,
),
TextFormField(
initialValue: contact.familyName ?? "",
decoration: const InputDecoration(labelText: 'Last name'),
onSaved: (v) => contact.familyName = v,
),
TextFormField(
initialValue: contact.prefix ?? "",
decoration: const InputDecoration(labelText: 'Prefix'),
onSaved: (v) => contact.prefix = v,
),
TextFormField(
initialValue: contact.suffix ?? "",
decoration: const InputDecoration(labelText: 'Suffix'),
onSaved: (v) => contact.suffix = v,
),
TextFormField(
decoration: const InputDecoration(labelText: 'Phone'),
onSaved: (v) =>
contact.phones = [Item(label: "mobile", value: v)],
keyboardType: TextInputType.phone,
),
TextFormField(
decoration: const InputDecoration(labelText: 'E-mail'),
onSaved: (v) =>
contact.emails = [Item(label: "work", value: v)],
keyboardType: TextInputType.emailAddress,
),
TextFormField(
initialValue: contact.company ?? "",
decoration: const InputDecoration(labelText: 'Company'),
onSaved: (v) => contact.company = v,
),
TextFormField(
initialValue: contact.jobTitle ?? "",
decoration: const InputDecoration(labelText: 'Job'),
onSaved: (v) => contact.jobTitle = v,
),
TextFormField(
initialValue: address.street ?? "",
decoration: const InputDecoration(labelText: 'Street'),
onSaved: (v) => address.street = v,
),
TextFormField(
initialValue: address.city ?? "",
decoration: const InputDecoration(labelText: 'City'),
onSaved: (v) => address.city = v,
),
TextFormField(
initialValue: address.region ?? "",
decoration: const InputDecoration(labelText: 'Region'),
onSaved: (v) => address.region = v,
),
TextFormField(
initialValue: address.postcode ?? "",
decoration: const InputDecoration(labelText: 'Postal code'),
onSaved: (v) => address.postcode = v,
),
TextFormField(
initialValue: address.country ?? "",
decoration: const InputDecoration(labelText: 'Country'),
onSaved: (v) => address.country = v,
),
],
),
),
),
);
}
}
推荐阅读
- r - 将 dplyr 转换为 data.table
- android - Android中的线程池,直接调用doinbackground
- javascript - 正方形内的多种颜色变化(填充)(P5.js)
- php - 创建“选择”以选择和显示所选国家/地区的问题
- python-3.x - ValueError:从 S3 存储桶加载 pkl 文件时出现“嵌入的空字节”
- tensorflow - “keras.backend.variable”在 keras 中的行为与 tensorflow 不同
- ruby - 为什么 Linux 上的 Ruby 对 File.writable 返回 true?('/tmp/file') 但在尝试写入文件时会引发 Errno::EACCES?
- javascript - PaperJS trouble creating circle on mouseDown
- php - MySQLi 面向对象的重定向取决于用户角色
- excel - 我的一些数据表列在 excel 中显示为数字数据类型如何防止将其定义为没有逗号分隔符的数字