【问题标题】:How to read contacts in Android using Realm?如何使用 Realm 在 Android 中读取联系人?
【发布时间】:2016-09-06 15:14:48
【问题描述】:

我找不到从 Android 读取联系人并将其保存在 Realm 中的任何解决方案。以前有人做过吗?

我知道我必须使用Contacts Provider,但这就是我所知道的。 AFAIK,Realm 不支持 Cursor 所以...还有什么?

编辑:

realm.executeTransaction(new Realm.Transaction() {
        @Override
        public void execute(Realm realm) {
            Contact realmContact = new Contact();
            String filter = "" + ContactsContract.Contacts.HAS_PHONE_NUMBER + " > 0 and "
                    + ContactsContract.CommonDataKinds.Phone.TYPE +"="
                    + ContactsContract.CommonDataKinds.Phone.TYPE_MAIN;

            Cursor phones = getActivity()
                    .getContentResolver()
                    .query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, filter, null, null);

            while (phones.moveToNext()) {
                String id = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID));
                String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
                realmContact.setId(id);
                realmContact.setName(name);
                realmContact.setNumber(phoneNumber);
                realmContact.setIsBeingSaved(true);
                realm.insertOrUpdate(realmContact);
            }

            /** merge mechanism */
            realm.where(Contact.class)
                    .equalTo("isBeingSaved", false)
                    .findAll()
                    .deleteAllFromRealm(); // delete all non-saved data
            for(Contact contact : realm.where(Contact.class).findAll()) {
                realmContact.setIsBeingSaved(false); // reset all save state
            }

联系人.class

public class Contact extends RealmObject{

@PrimaryKey
private String id;

@Index
private String name;

@Index
private String number;

@Index
private boolean isBeingSaved;

public String getId() {
    return id;
}

public void setId(String id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getNumber() {
    return number;
}

public void setNumber(String number) {
    this.number = number;
}

public boolean getIsBeingSaved() {
    return isBeingSaved;
}

public void setIsBeingSaved(boolean beingSaved) {
    isBeingSaved = beingSaved;
}

}

【问题讨论】:

  • 读取联系人并将其存储在数据库中是两个完全独立的操作。从阅读开始,如果成功,请担心将它们存储在领域中
  • copyToRealmOrUpdate()的返回值被忽略时,insertOrUpdate()是一个更优化(更节省内存)的解决方案。
  • 重复问题很常见,如果你在谷歌搜索duplication whatsapp stack overflow,你会找到其他答案。我认为人与人之间的电话号码必须唯一的假设有点硬核,即使我的联系人也会打破它。

标签: android realm


【解决方案1】:

创建RealmObject,从content provider读取数据,将数据保存到RealmObject,将数据保存到Realm中:

// background thread
Realm realm = null;
try {
    realm = Realm.getDefaultInstance();
    realm.executeTransaction(new Realm.Transaction() {
        @Override
        public void execute(Realm realm) {
            RealmContact realmContact = new RealmContact();
            Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
            while (phones.moveToNext()) {
               String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
               String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
               realmContact.setName(name);
               realmContact.setPhoneNumber(phoneNumber);
               realm.insertOrUpdate(realmContact);
            }
        }
    });
} finally {
    if(realm != null) {
        realm.close();
    }
}

编辑:好的,这是合并数据并删除不在您保存的列表中的所有数据的技巧

public class RealmContract extends RealmObject {
    @PrimaryKey
    private long id;

    @Index
    private String name;

    @Index
    private String phoneNumber;

    @Index
    private boolean isBeingSaved;

    //getters, setters
}

然后合并:

// background thread
Realm realm = null;
try {
    realm = Realm.getDefaultInstance();
    realm.executeTransaction(new Realm.Transaction() {
        @Override
        public void execute(Realm realm) {
            RealmContact realmContact = new RealmContact();
            Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, null, null, null);
            while (phones.moveToNext()) {
               String id = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds._ID));
               String name = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
               String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
               realmContact.setId(id);
               realmContact.setName(name);
               realmContact.setPhoneNumber(phoneNumber);
               realmContact.setIsBeingSaved(true);
               realm.insertOrUpdate(realmContact);
            }
            realm.where(RealmContact.class)
                 .equalTo(RealmContactFields.IS_BEING_SAVED, false) // compile 'dk.ilios:realmfieldnameshelper:1.0.0'
                 .findAll()
                 .deleteAllFromRealm(); // delete all non-saved data
            for(RealmContact realmContact : realm.where(RealmContact.class).findAll()) { // realm 0.89.0+
                realmContact.setIsBeingSaved(false); // reset all save state
            }
        }
    });
} finally {
    if(realm != null) {
        realm.close();
    }
}

编辑:请参阅 OP 的其他问题以可靠地读取联系人数据(因为联系人 LOOKUP_ID 存在问题并确保 ID 正确):Obtaining contacts from content provider without duplicates or invalid contacts, and save to Realm

【讨论】:

  • 这太棒了!谢谢!
  • 还有一个问题:如果联系人在手机上被删除,它会保留在数据库中 - 如何更新它以反映更改?
  • 如果您还获得了 ContactsContract.Contacts._ID 并将其用作主键,那么您可以跟踪应用中的用户。当我使用 PC 时,我将用代码对此做出回应,说明如何在写入事务中轻松添加新元素和删除不存在的元素。
  • 我做try-finally 的事情是为了确保无论发生什么,Realm 都是关闭的。在后台线程上关闭 Realm 实例非常重要。
  • 我认为 this 问题已得到解答(因为评论树变得太长)并且我保证合并有效,因为我在生产和其他东西中使用它,但如果你问关于删除失败的新问题,我会回答这个问题:p
【解决方案2】:

您可以创建一个模型类来存储联系人所需的数据

然后在模型类中使用Cursor获取数据和设置数据。

将光标数据保存在模型对象列表中。

然后在单个事务中插入所有模型对象,因为每个对象事务有开销并减慢我们的应用程序

【讨论】:

    猜你喜欢
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-20
    相关资源
    最近更新 更多