使用CursorLoader获得邮件会导致邮件重复(Using CursorLoader to ge

2019-08-16 18:05发布

我想获得的用途联系人的电子邮件ID。 对于我使用光标装载机。 有一个问题我收到重复的电子邮件ID也。 如何删除电子邮件duplicacy。 我应该使用原始查询“SELECT DISTINCT”而不是使用CursorLoader或者有一些其他的解决办法?

@Override
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
    String[] projection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME, ContactsContract.CommonDataKinds.Email.DATA};
    String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + "  COLLATE LOCALIZED ASC";
    String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP +"='1' AND " + Email.DATA +" IS NOT NULL AND " + Email.DATA +" != \"\" " ;

    //showing only visible contacts  
    String[] selectionArgs = null;
    return new CursorLoader(this, ContactsContract.CommonDataKinds.Email.CONTENT_URI, projection, selection, selectionArgs, sortOrder);
}

Answer 1:

我最近就遇到了这个问题。 看来,CursorLoader不具备的“不同”的实现。 我的解决办法增加了几行到onLoadFinish方法和扩展了BaseAdapter接受一个列表参数:

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    String projection[] = {
            CommonDataKinds.Phone._ID,
            CommonDataKinds.Phone.DISPLAY_NAME,
    };      
    String select = "((" + CommonDataKinds.Phone.DISPLAY_NAME + " NOTNULL) and " + CommonDataKinds.Phone.HAS_PHONE_NUMBER + " > 0)";
    String sort = CommonDataKinds.Phone.DISPLAY_NAME + " ASC";

    CursorLoader loader = new CursorLoader(
            mContext, 
            CommonDataKinds.Phone.CONTENT_URI,
            projection,
            select,
            null,
            sort
            );  

    return loader;
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    List<String> displayNames = new ArrayList<String>();
    cursor.moveToFirst();

    while(!cursor.isAfterLast()){
        String name = cursor.getString(cursor.getColumnIndex(CommonDataKinds.Phone.DISPLAY_NAME));

        if(!displayNames.contains(name))
            displayNames.add(name);

        cursor.moveToNext();
    }

    mAdapter.swapCursor(displayNames);
}

这里是我的BaseAdapter类:

public class AdapterAddContacts extends BaseAdapter{
private List<String> mData = new ArrayList<String>();
private Context mContext;

public AdapterAddContacts(Context context,List<String> displayNames){
    mData = displayNames;
    mContext = context;
}   

@Override
public int getCount() {
    if(mData != null)
        return mData.size();
    else
        return 0;
}

@Override
public Object getItem(int pos) {
    return mData.get(pos);
}

@Override
public long getItemId(int id) {
    return id;
}

@Override
public View getView(int pos, View convertView, ViewGroup parent) {
    LayoutInflater inflater = LayoutInflater.from(mContext);
    View view = inflater.inflate(R.layout.entry_add_contacts,parent,false);

    String data = mData.get(pos);                           

    TextView textName = (TextView)view.findViewById(R.id.my_contacts_add_display_name);
    textName.setText(data);
    textName.setTag(data);          

    return view;
}   

public void swapCursor(List<String> displayNames){
    mData = displayNames;
    this.notifyDataSetChanged();
}

你应该能够专门修改此为您的需求。



Answer 2:

通过@mars启发,我不需要适配器的修改的解决方案。 我们的想法是删除光标的复印件; 因为没有办法做到这一点,我们创建了一个新的游标的内部消除重复。

所有的代码是在onLoadFinished

@Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {

        MatrixCursor newCursor = new MatrixCursor(PROJECTION); // Same projection used in loader 
        if (cursor.moveToFirst()) {
            String lastName = "";
            do {
                if (cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME)).compareToIgnoreCase(lastName) != 0) {

                    newCursor.addRow(new Object[]{cursor.getString(0), cursor.getString(1), cursor.getString(2) ...}); // match the original cursor fields
                    lastName =cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
                }
            } while (cursor.moveToNext());
        }
        mContactsAdapter.swapCursor(newCursor);
    }


Answer 3:

我曾经在我的项目一个小型的黑客 - SQL注入,这样的:

@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    return new CursorLoader(
            this,
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            new String[] {
                "DISTINCT "+ MediaStore.Images.Media.BUCKET_ID,
                MediaStore.Images.Media.BUCKET_DISPLAY_NAME},
            null, null, null);
}

此代码只返回包名称和画廊它们的ID。 所以,我想重写代码这样的:

@Override
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
    String[] projection = new String[] {
        "DISTINCT " + ContactsContract.Contacts._ID,
        ContactsContract.Contacts.DISPLAY_NAME,
        ContactsContract.CommonDataKinds.Email.DATA};
    String sortOrder = ContactsContract.Contacts.DISPLAY_NAME + "  COLLATE LOCALIZED ASC";
    String selection = ContactsContract.Contacts.IN_VISIBLE_GROUP +"='1' AND " + Email.DATA +" IS NOT NULL AND " + Email.DATA +" != \"\" " ;

    //showing only visible contacts  
    String[] selectionArgs = null;
    return new CursorLoader(this, ContactsContract.CommonDataKinds.Email.CONTENT_URI, projection, selection, selectionArgs, sortOrder);
}


Answer 4:

你可以把setDistinct在你的内容提供商。

    @Override 
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    ...
    final SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
    qb.setDistinct(true);


Answer 5:

如果你担心性能,不希望在onLoadFinished()再次玩弄光标,然后有一个小黑客

我结合以下从SO两种解决方案。

  1. 选择在机器人源码不同值

  2. 与rawQuery CursorLoader

这里是我工作的解决方案:

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
    String tableName;

    /*
     * Choose the table to query and a sort order based on the code returned
     * for the incoming URI.
     */
    switch (uriMatcher.match(uri)) {
        case NOTIFICATION:
            tableName = NOTIFICATIONS_TABLE_NAME;

            break;

        case NOTIFICATION_TIMESTAMP:

            Cursor cursor = db.query(true, NOTIFICATIONS_TABLE_NAME, projection, selection, selectionArgs, TIMESTAMP, null, sortOrder, null);
            cursor.setNotificationUri(getContext().getContentResolver(), uri);

            return cursor;

        case DOWNLOAD:
            tableName = DOWNLOADS_TABLE;
            break;
        default:
            throw new IllegalArgumentException("Unknown URI " + uri);
    }


    if (selection != null) {
        selection = selection + "=?";
    }

    Cursor cursor = db.query(tableName, projection, selection, selectionArgs, null, null, sortOrder);


    // Tell the cursor what uri to watch, so it knows when its source data
    // changes
    cursor.setNotificationUri(getContext().getContentResolver(), uri);
    return cursor;
}

如果在这种情况下,表名看到的是同样是前2个案件,但我创建了一个虚拟URI来实现这一目标。 可能不是一个很好的做法,但完美的作品。



Answer 6:

我发现了一个解决方案中使用DISTINCT在选择阵列关键字。

String[] projection = new String[] { ContactsContract.Contacts._ID, ContactsContract.Contacts.DISPLAY_NAME, "DISTINCT" + ContactsContract.CommonDataKinds.Email.DATA};


文章来源: Using CursorLoader to get emails causes duplication of emails