【问题标题】:Android and SQLite : is there no good way to join queries with the ContactsContract APIAndroid 和 SQLite:有没有很好的方法来使用 ContactsContract API 加入查询
【发布时间】:2012-06-16 15:25:27
【问题描述】:

我觉得我可能在 ContactsContract API 中遗漏了一些东西。在我的应用程序中,我有几个 SQLite 表,其中引用了联系人或组(来自 ContactsContract API)。我这样做了,而不是用我自己的联系人和组表重新发明轮子。

然而,使查询协同工作变成了一场噩梦。假设我想使用来自特定组的所有联系人对我的 SQL 表执行操作。我必须查询 ContactsContract 以获取组成员的contact_id,将这些contact_id 加入字符串,然后将该字符串放入单独的查询中。 (或者循环使用 SQL 查询。)

这是一个糟糕的 SQL,我觉得我一定做错了什么,但我找不到任何其他方法的参考。我即将维护自己的联系人列表。有什么想法吗?

【问题讨论】:

    标签: android sql contactscontract


    【解决方案1】:

    不,你没有处于任何错误的边缘。 Contacts ContentProvider(以及我见过的几乎所有 ContentProvider)都与传统的 SQL 智慧相矛盾,哦,好吧。

    如果您想从多种类型的 ContactsContracts.CommonDataKinds 中获取数据,您需要检测您所在行的 mime-type 并确定它是哪种实体(或进行额外查询,我的首选解决方案是在一个查询中完成所有操作...)

    屏住呼吸,这是我为执行此类操作而编写的一些代码示例。您应该能够看到不同的行是如何成为不同类型的实体的,因此它们的通用列可以保存不同类型的数据,这就是我们使用 CommonDataKinds.* 类在上下文中引用它们的原因:

    public class ContactsHelper {
    
    
        private static String[] PROJECTION = {
            Data.CONTACT_ID,
            Data.MIMETYPE,
            StructuredName.GIVEN_NAME,
            StructuredName.FAMILY_NAME,
            StructuredName.DISPLAY_NAME,
            StructuredName.MIDDLE_NAME,
            Email.ADDRESS
        };
    
        public static void readContacts(Context context) {
            ContentResolver resolver = context.getContentResolver();
            Uri contactsUri = ContactsContract.Data.CONTENT_URI;
    
            SQLiteDatabase conn = DatabaseHelper.openDatabase(context);
    
            Cursor cursor = resolver.query(contactsUri, PROJECTION, null, null, null);
    
            int idxContactId = cursor.getColumnIndex(Data.CONTACT_ID);
            int idxMimeType = cursor.getColumnIndex(Data.MIMETYPE);
            int idxGivenName = cursor.getColumnIndex(StructuredName.GIVEN_NAME);
            int idxFamilyName = cursor.getColumnIndex(StructuredName.FAMILY_NAME);
            int idxDisplayName = cursor.getColumnIndex(StructuredName.DISPLAY_NAME);
            int idxMiddleName = cursor.getColumnIndex(StructuredName.MIDDLE_NAME);
            int idxEmail = cursor.getColumnIndex(Email.ADDRESS);
    
            for (cursor.moveToFirst(); ! cursor.isAfterLast(); cursor.moveToNext()) {
                String mimeType = cursor.getString(idxMimeType);
    
                Integer contactId = cursor.getInt(idxContactId);
    
                if (StructuredName.CONTENT_ITEM_TYPE.equals(mimeType)) {
                    String firstName = cursor.getString(idxGivenName);
                    String middleName = cursor.getString(idxMiddleName);
                    String lastName = cursor.getString(idxFamilyName);
                    String displayName = cursor.getString(idxDisplayName);
    
                                Log.d(TAG, all the values ^^^);
    
                }
    
    
                if (Email.CONTENT_ITEM_TYPE.equals(mimeType)) {
                    String emailName = cursor.getString(idxEmail);
                    Log.d(TAG, all the values ^^^);
                }
            }
    
            DatabaseHelper.closeDatabase(conn);
            cursor.close();
        }   
    }
    

    是的,这个完全严肃的解决方案确实使用了字符串比较。如果有更好的方法,请告诉我!

    【讨论】:

    • 哇,这太奇怪了。忏悔:在等待这个答案之前,我给了我自己的联系人表。我的函数更短更优雅;我写的助手类已经被淘汰了;我的代码看起来好多了。我相信它也更有效率。感谢您的帮助和回答。
    • 我也会这样做。如果您有复杂的问题需要解决,只需观察联系人并将其导入您自己的数据库,这样您就可以实际使用 SQL!
    • 我想 One 可以改进您的代码,但它仍然非常清晰且非常有帮助。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多