CalendarProvider:通过多个ID查询日历将返回一个空光标

时间:2017-07-13 16:17:11

标签: java android android-sqlite

我想从CalendarProvider API查询日历。在我的应用程序的设置中,用户可以检查并取消选中他想在我的应用程序中使用哪些日历。我使用的表USEDCALENDARS得到了_id(int),calendar_id(int)和used(int)列。

现在我想展示一个Spinner,其中包含用户选择的每个可写日历。我的方法是:从USEDCALENDARS收集所有calendar_ids,其中used = 1(true)。然后使用收集的id作为queryparam查询CalendarProvider。请在这里查看我的代码。

    //using a simple list as calendarIds because the code that collects the id is working perfectly
    List<Long> calendarIds = Arrays.asList(1L,2L,3L);
    String selection = Calendars._ID + " IN (?)";
    String joinedCalendarIds = StringUtils.join(calendarIds, ", ");

    String[] selectionArgs = new String[]{
            joinedCalendarIds
    };
    return cr.query(Calendars.CONTENT_URI, GOOGLE_CALENDARS_PROJECTION, selection,selectionArgs, Calendars.CALENDAR_DISPLAY_NAME);

这是返回一个空光标。但是如果你用代码的第一行交换。 List<Long> calendarIds = Arrays.asList(1L);(基本上将ID数量限制为1),将返回正确的日历。

我走向错误的方向吗?为什么这不起作用?有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

我认为问题在于如何解析paramneterised IN 子句。

我按照以下代码做了一些测试(4): -

    String[] selectionargs = {"1","2","3"};
    String[] oldselectionargs = {"1,2,3"};
    SQLiteDatabase db = mydbhelper.getWritableDatabase();
    String oldselection = "_id IN(?)";
    String selection =  "_id" + " IN (";
    String selection4 = "_id IN (";
    for (int i=0; i < selectionargs.length; i++) {
        if (i > 0) {
            selection = selection + ", ";
        }
        selection = selection + selectionargs[i];
    }
    selection = selection + ")";
    String[] columns = {mydbhelper.MYFLOATCOL};
    Cursor cursor = db.query(mydbhelper.TESTFLOATTABLE,columns,selection,null,null,null,null);
    Log.d("DBIN","Cursor Count=" + cursor.getCount());
    while (cursor.moveToNext()) {
        Log.d("DBIN",cursor.getString(cursor.getColumnIndex(mydbhelper.MYFLOATCOL)));
    }

    Cursor cursor2 = db.query(mydbhelper.TESTFLOATTABLE,columns,oldselection,oldselectionargs,null,null,null);
    Log.d("DBIN","Cursor Count=" + cursor2.getCount());
    while (cursor2.moveToNext()) {
        Log.d("DBIN",cursor2.getString(cursor2.getColumnIndex(mydbhelper.MYFLOATCOL)));
    }

    Cursor cursor3 = db.query(mydbhelper.TESTFLOATTABLE,columns,
            "_id IN (" + oldselectionargs[0].toString() + ")",null,null,null,null);
    Log.d("DBIN","Cursor Count=" + cursor3.getCount());
    while (cursor3.moveToNext()) {
        Log.d("DBIN",cursor3.getString(cursor3.getColumnIndex(mydbhelper.MYFLOATCOL)));
    }

    for (int i=0; i < selectionargs.length; i++) {
        if (i > 0) {
            selection4 = selection4 + ",";
        }
        selection4 = selection4 + "?";
    }
    selection4 = selection4 + ")";

    Cursor cursor4 = db.query(mydbhelper.TESTFLOATTABLE,columns,selection4,selectionargs,null,null,null);
    Log.d("DBIN","Cursor Count=" + cursor4.getCount());
    while (cursor4.moveToNext()) {
        Log.d("DBIN",cursor4.getString(cursor4.getColumnIndex(mydbhelper.MYFLOATCOL)));
    }

    cursor.close();
    cursor2.close();
    cursor3.close();
    cursor4.close();

以上代码的输出: -

07-14 13:55:54.717 23634-23634/? D/DBIN: Cursor Count=3
07-14 13:55:54.717 23634-23634/? D/DBIN: 100
07-14 13:55:54.717 23634-23634/? D/DBIN: 200
07-14 13:55:54.717 23634-23634/? D/DBIN: 300
07-14 13:55:54.718 23634-23634/? D/DBIN: Cursor Count=0
07-14 13:55:54.720 23634-23634/? D/DBIN: Cursor Count=3
07-14 13:55:54.720 23634-23634/? D/DBIN: 100
07-14 13:55:54.720 23634-23634/? D/DBIN: 200
07-14 13:55:54.720 23634-23634/? D/DBIN: 300
07-14 13:55:54.721 23634-23634/? D/DBIN: Cursor Count=3
07-14 13:55:54.721 23634-23634/? D/DBIN: 100
07-14 13:55:54.721 23634-23634/? D/DBIN: 200
07-14 13:55:54.721 23634-23634/? D/DBIN: 300

因此第1,第3和第4种方法起作用(即光标,cursor3和cursor4返回预期值),第2次传递“1,2,3”作为参数不起作用(即你尝试的方式)。

  • 第一个,使用cursor1,使用一个值数组并构建一个逗号 包含在选择中的分隔字符串 selectionargs为null。

  • 第二个,使用cursor2,基本上是什么 你试过

  • 第3只使用硬编码字符串,即真的没有 与第1次不同

  • 第4个构建WHERE(IN)子句,其中包含要传递的适当数量的参数,例如.... IN (?,?,?)并使用最初定义的selectionargs数组。