我有一个联系人列表,我正尝试使用 contacts_service 将其加载到 ListView 中。插入。对于每个联系人,我想首先检查他们是否已被标记为 isFavourite,这是通过检查他们的 ID 是否在 SharedPreferences 的列表中来确定的。如果是这样,那么我们会在他们的名字旁边显示一个星号。
因为检查 SharedPreferences 需要一个 Future,我该如何完成呢?到目前为止的进展如下。
联系人屏幕:
@override
Widget build(BuildContext context) {
return Scaffold(
body: ListView.builder(
itemCount: contacts?.length,
itemBuilder: (BuildContext context, int index) {
Contact c = contacts?.elementAt(index);
return ListTile(
// Show star next to Contact's name
leading: c.isFavourite ? Icon(Icons.star) : null,
title: Text(c.name);
);
}
);
);
}
共享首选项:
static Future<bool> checkIsFavourite(String contactId) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
List<String> favouriteContacts = prefs.getStringList("Favourites");
return favouriteContacts.contains(contactId);
}
联系人服务:
class ContactsService {
static const MethodChannel _channel =
MethodChannel('github.com/clovisnicolas/flutter_contacts');
/// Fetches all contacts, or when specified, the contacts with a name
/// matching [query]
static Future<Iterable<Contact>> getContacts(
{String query, bool withThumbnails = true}) async {
Iterable contacts = await _channel.invokeMethod('getContacts',
<String, dynamic>{'query': query, 'withThumbnails': withThumbnails});
return contacts.map((m) => Contact.fromMap(m));
}
联系类:
class Contact {
Contact(
{this.givenName,
this.middleName,
this.prefix,
this.suffix,
this.familyName,
this.company,
this.jobTitle,
this.emails,
this.phones,
this.postalAddresses,
this.avatar,
this.note,
this.isSelected});
String identifier,
displayName,
givenName,
middleName,
prefix,
suffix,
familyName,
company,
jobTitle,
note;
Iterable<Item> emails = [];
Iterable<Item> phones = [];
Iterable<PostalAddress> postalAddresses = [];
Uint8List avatar;
bool isSelected;
String initials() {
return ((this.givenName?.isNotEmpty == true ? this.givenName[0] : "") +
(this.familyName?.isNotEmpty == true ? this.familyName[0] : ""))
.toUpperCase();
}
Contact.fromMap(Map m) {
identifier = m["identifier"];
displayName = m["displayName"];
givenName = m["givenName"];
middleName = m["middleName"];
familyName = m["familyName"];
prefix = m["prefix"];
suffix = m["suffix"];
company = m["company"];
jobTitle = m["jobTitle"];
emails = (m["emails"] as Iterable)?.map((m) => Item.fromMap(m));
phones = (m["phones"] as Iterable)?.map((m) => Item.fromMap(m));
postalAddresses = (m["postalAddresses"] as Iterable)
?.map((m) => PostalAddress.fromMap(m));
avatar = m["avatar"];
note = m["note"];
isSelected = SharedPreferences.checkIsFavourite(m["identifier"]);
// What is the correct way to check if it's a favourite?
}
最佳答案
我建议定义一个在应用启动时初始化的应用范围的 super 变量。
例如main.dart
SharedPreferences prefs;
void main() async {
prefs = await SharedPreferences.getInstance();
return runApp(MyApp());
}
然后你可以通过prefs变量以构造函数参数的形式传递给需要的任何其他屏幕/小部件。例如
class ContactsScreen extends StatefulWidget {
ContactsScreen({
Key key,
@required this.prefs,
}):
super(key: key);
final SharedPreferences prefs;
...
}
您可能已经注意到在您的代码中 SharedPreferences每次在 ListView 中建立联系时都会调用初始化, 其次是 prefs.getStringList("Favourites")打电话。
这两个是相对繁重的操作,如果您定义一次收藏夹数组并将其用于每个联系人构建调用,则可以避免这些操作。
我会怎么做是创建 isFavourite在 Contact 中发挥作用接受 List<String> 的对象作为论据。例如
class Contact {
...
bool isFavourite(List<String> favouriteIds) {
assert(favouriteIds != null);
return favouriteIds.contains(this.identifier);
}
...
}
并在联系人屏幕中 build :
final List<String> favouriteIds = prefs.getStringList("Favourites") ?? []; // Use empty array in case `Favourites` is not set
...
ListTile(
// Show star next to Contact's name
leading: contact.isFavourite(favouriteIds) ? Icon(Icons.star) : null,
title: Text(contact.name);
);
...
但是,我必须警告你,我不知道在 Dart/Flutter 中如何处理全局(/ super /应用范围)变量,也不知道声明 (已更新)main() 是否是个好主意。方法为 async ,因此使用它需要您自担风险。
根据我的个人经验 - 到目前为止我还没有遇到任何问题。
已更新
结果声明 main()作为async如果perfectly safe .
至于全局变量——我的方法是可以的,尽管有一个 even better one .
关于listview - 查询 ListView 中每一项的 SharedPreferences,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56127287/
我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.
在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg
我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这
我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr
我正在尝试查询我的Rails数据库(Postgres)中的购买表,我想查询时间范围。例如,我想知道在所有日期的下午2点到3点之间进行了多少次购买。此表中有一个created_at列,但我不知道如何在不搜索特定日期的情况下完成此操作。我试过:Purchases.where("created_atBETWEEN?and?",Time.now-1.hour,Time.now)但这最终只会搜索今天与那些时间的日期。 最佳答案 您需要使用PostgreSQL'sdate_part/extractfunction从created_at中提取小时
给定一个nxmbool数组:[[true,true,false],[false,true,true],[false,true,true]]有什么简单的方法可以返回“该列中有多少个true?”结果应该是[1,3,2] 最佳答案 使用转置得到一个数组,其中每个子数组代表一列,然后将每一列映射到其中的true数:arr.transpose.map{|subarr|subarr.count(true)}这是一个带有inject的版本,应该在1.8.6上运行,没有任何依赖:arr.transpose.map{|subarr|subarr.in
我在Rails上使用带有ruby的solr。一切正常,我只需要知道是否有任何现有代码来清理用户输入,比如以?开头的查询。或* 最佳答案 我不知道执行此操作的任何代码,但理论上可以通过查看parsingcodeinLucene来完成并搜索thrownewParseException(只有16个匹配!)。在实践中,我认为您最好只捕获代码中的任何solr异常并显示“无效查询”消息或类似信息。编辑:这里有几个“sanitizer”:http://pivotallabs.com/users/zach/blog/articles/937-s
我正在为锦标赛开发一个Rails应用程序。我在这个查询中使用了三个模型:classPlayertruehas_and_belongs_to_many:tournamentsclassTournament:destroyclassPlayerMatch"Player",:foreign_key=>"player_one"belongs_to:player_two,:class_name=>"Player",:foreign_key=>"player_two"在tournaments_controller的显示操作中,我调用以下查询:Tournament.where(:id=>params
在我的路线文件中我有:match'graphs/(:id(/:action))'=>'graphs#(:action)'如果是GET请求(工作)或POST请求(不工作),我想匹配它我知道我可以使用以下方法在资源中声明POST请求:post'/'=>:show,:on=>:member但是我怎样才能为比赛做到这一点呢?谢谢。 最佳答案 如果你同时想要POST和GETmatch'graphs/(:id(/:action))'=>'graphs#(:action)',:via=>[:get,:post]编辑默认值可以设置如下match'g
我想用sunspot重现以下原始solr查询q=exact_term_text:fooORterm_textv:foo*ORalternate_text:bar*但我无法通过标准的太阳黑子界面理解这是否可能以及如何实现,因为看起来:fulltext方法似乎不接受多个文本/搜索字段参数我不知道将什么参数作为第一个参数传递给fulltext,就好像我通过了"foo"或"bar"结果不匹配如果我传递一个空参数,我得到一个q=*:*范围过滤器(例如with(:term).starting_with('foo*')(顾名思义)作为过滤器查询应用,因此不参与评分。似乎可以手动编写字符串(或者可能使