【问题标题】:Android - Remove Duplicate ContactsAndroid - 删除重复的联系人
【发布时间】:2021-02-08 13:12:40
【问题描述】:

我正在尝试在 Recycler View 中显示联系人,一切正常,但联系人显示两次或三次。

这是代码

 RecyclerView recyclerView;
 List<Contacts> contactsList;
 ContactsAdapter adapter;

 public void getContactList() {
    Cursor cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
            null, null, null,
            "UPPER(" + ContactsContract.Contacts.DISPLAY_NAME + ") ASC");
    while (cursor.moveToNext()) {
        String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
        String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

        Contacts contacts = new Contacts(name, number);
        if (contactsList.contains(contacts)){
            cursor.moveToNext();
        }
        else {
            contactsList.add(contacts);
        }
        adapter = new ContactsAdapter(contactsList, getApplicationContext());
        recyclerView.setAdapter(adapter);

        adapter.notifyDataSetChanged();
    }
}

那么,我该如何解决这个问题呢?

【问题讨论】:

  • 您没有在任何地方清除列表...也许该函数不止一次发生并且值一次又一次地添加到列表中?

标签: android contacts


【解决方案1】:

只传递 phoneNumber 作为键和 phoneName 作为值 您可以使用:

Map<String, String> map = new HashMap<>();
map.put("A", "1");
...
System.out.printf("Before: %s%n", map);

// Set in which we keep the existing values
Set<String> existing = new HashSet<>();
map = map.entrySet()
    .stream()
    .filter(entry -> existing.add(entry.getValue()))
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
System.out.printf("After: %s%n", map);  

例如:

Before: {A=1, B=2, C=2, D=3, E=3} After: {A=1, B=2, D=3}

【讨论】:

  • 那么,我应该传递姓名和电话号码还是传递联系人对象?
【解决方案2】:

您可以使用 HashSet 更改 List。 HashSet 防止有重复项。你的最终代码应该是这样的:

 RecyclerView recyclerView;
 HashSet<Contacts> contactsSet;
 ContactsAdapter adapter;

 public void getContactList() {
    Cursor cursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
            null, null, null,
            "UPPER(" + ContactsContract.Contacts.DISPLAY_NAME + ") ASC");
    while (cursor.moveToNext()) {
        String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
        String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));

        Contacts contacts = new Contacts(name, number);
        contactsSet.add(contacts);
    }
    List<Contacts> contactsList = new ArrayList<>();
    adapter = new ContactsAdapter(contactsList, getApplicationContext());
    recyclerView.setAdapter(adapter);
    adapter.notifyDataSetChanged();
}

【讨论】:

    【解决方案3】:

    我认为您应该考虑几个问题。是查询错误还是我保存联系人的方式错误?

    在您的应用中是否应该允许复制联系人?如果没有,您可以在迁移中添加 unique constraint。见Sql Lite Unique Constraints

    如果您的数据库应该接受重复值,那么您应该添加一列来表示该用户的唯一值吗?即 userId 列或联系人关联的位置,然后将其作为 Selection 和 SelectionArgs 添加到您的查询中。

    最后,如果您只是在寻找快速解决方案...您应该更深入地研究您的过滤。

    您的代码contactsList.contains(contacts) 永远不会是真的,因为您总是在上面一行中创建联系人。然后,您正在检查您的列表是否包含新创建的列表。否则可以使用上面的解决方案https://stackoverflow.com/a/64535787/5398130

    【讨论】:

      【解决方案4】:

      您可以覆盖联系人类中的 equals() 方法。这样,如果您的覆盖方法中两个联系人对象在逻辑上相等,则您的 contactList.contains(Contact c) 可以评估为 true,因此它不会再次将其添加到列表中。

           @Override
           public boolean equals(Object o){
                if(!o.getClass().equals(Contacts.class)) return false;
                Contact c2 = (Contact)o;
                // if phonenumber is unique to differentiate contact
                return c2.number.equals(number);
            }
      

      【讨论】:

        【解决方案5】:

        您可以按照此页面上的这些步骤操作,我可以在这里提供完整的解决方案是link

        【讨论】:

          猜你喜欢
          • 2013-11-18
          • 1970-01-01
          • 2014-02-14
          • 1970-01-01
          • 2017-07-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多