在 Adapter 或 Fragment 中为 ContactsContract 设置数据的 MIMETYPE
Posted
技术标签:
【中文标题】在 Adapter 或 Fragment 中为 ContactsContract 设置数据的 MIMETYPE【英文标题】:Setting MIMETYPE of Data for ContactsContract in Adapter or Fragment 【发布时间】:2018-08-10 06:57:24 【问题描述】:在我的应用程序中,我希望显示
的联系方式ContactsContract.CommonDataKinds.Organization.TITLE
在 ContactsContract 中,MIMETYPE 用于选择手机中大部分有用数据的列的标识。
我正在寻求在我的列表视图中显示联系人的职位。我在 WHERE/SELECTION 子句中使用了 IN 的 SQL 注入,代码如下。
private static final String SELECTION =
ContactsContract.RawContactsEntity.MIMETYPE + " IN ('" +
ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE + "')";
这是可行的,因为它在 where 子句中删除了此处没有值的项目,这在很大程度上减少了列表中的项目数量。
如上所述,我正在寻找如何在我的 CursorLoader 或我的 CursorAdapter 中设置光标的 MIMETYPE。
绑定适配器方法如下所示
public void onBindViewHolder(ContactsViewHolder viewHolder, Cursor cursor)
String profession = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.TITLE));
String contactID = cursor.getString(cursor.getColumnIndex( ContactsContract.Data.CONTACT_ID));
Uri contactURI = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI,
Integer.parseInt(contactID));
viewHolder.setProfession(profession);
viewHolder.setURI(contactURI);
CursorLoader 看起来像这样。 FROM_COLUMNS 包含基本数据,包括
ContactsContract.CommonDataKinds.Organization.TITLE
return new CursorLoader(
getContext(),
ContactsContract.Data.CONTENT_URI,
FROM_COLUMNS,
null,
null,
null
);
【问题讨论】:
【参考方案1】:您现在所做的基本上是在联系人数据库中显示所有职位的列表,并获取每个职位的联系人 ID。
如果我理解正确,您想要实现的是在数据库中显示所有联系人的列表,如果联系人包含职位,则将其显示在联系方式?
如果是这样,您不能在 Data.CONTENT_URI
上创建 CursorLoader,因为它包含每个数据一项,即每个联系人可能包含许多数据行。
您可以完全避免使用 CursorLoader,并遍历 Data
中的所有项目 - 将它们存储在内存中的某个 HashMap 中,然后创建一个 ListView/RecyclerView 适配器以在屏幕上显示 HashMap。
下面是帮助您入门的代码(考虑创建一个自定义对象来包含联系信息,而不是我在下面使用的字符串列表):
Map<Long, List<String>> contacts = new HashMap<Long, List<String>>();
String[] projection = Data.CONTACT_ID, Data.DISPLAY_NAME, Data.MIMETYPE, Data.DATA1 ;
// select only contacts that have at least one phone, email or job
String selection = Data.MIMETYPE + " IN ('" + Phone.CONTENT_ITEM_TYPE + "', '" + Email.CONTENT_ITEM_TYPE + "', '" + Organization.CONTENT_ITEM_TYPE + "')";
Cursor cur = cr.query(Data.CONTENT_URI, projection, selection, null, null);
while (cur != null && cur.moveToNext())
long id = cur.getLong(0);
String name = cur.getString(1);
String mime = cur.getString(2); // type of data: email / phone / company
String data = cur.getString(3); // the actual info, e.g. +1-212-555-1234
switch (mime)
case Phone.CONTENT_ITEM_TYPE:
kind = "phone";
break;
case Email.CONTENT_ITEM_TYPE:
kind = "email";
break;
case Organization.CONTENT_ITEM_TYPE:
kind = "job";
break;
Log.d(TAG, "got " + id + ", " + name + ", " + data);
// add info to existing list if this contact-id was already found, or create a new list in case it's new
List<String> infos;
if (contacts.containsKey(id))
infos = contacts.get(id);
else
infos = new ArrayList<String>();
infos.add("name = " + name);
contacts.put(id, infos);
infos.add(kind + "= " + data);
【讨论】:
感谢您的指导。使用 loader 的好处之一是增加了安全性,而且 Loader 内置了一个 ContentObserver,我也很喜欢。可能必须继续研究以挖掘最佳方法。这可能对某人有帮助 gist.github.com/piyush-malaviya/… 不确定安全优势是什么,但 contentObserver 应该很容易添加 我认为核心问题在于选择子句,因为我不仅要检索有专业的项目,还要检索没有专业的项目。这里有什么线索吗?MIMETYPE IN (...)
是 OR 选择,因此您应该获取所有联系人(没有电话、电子邮件或组织的联系人除外)
我使用了 Map 方法和自定义对象,并且取得了不错的进展。以上是关于在 Adapter 或 Fragment 中为 ContactsContract 设置数据的 MIMETYPE的主要内容,如果未能解决你的问题,请参考以下文章
在 Fragment 中使用 Spinner 和 Adapter
Fragment的Adapter和新的Fragment如何建立通信?
从 Adapter 向 Fragment 发送数据并在 Fragment 中获取
为啥 recyclerview$adapter 在片段中为空