Android 连接游标和排序

Android 连接游标和排序,android,cursor,mediastore,Android,Cursor,Mediastore,我正在为Android写一个“画廊类型”的应用程序。在“主活动”中,我有一个GridView,我想用设备上照片的缩略图加载/填充它。因此,我编写了一个ContentProvider,其中query方法从MediaStore.Media.Thumbnails返回一个游标 但是,我还想显示MediaStore.Media.Images中的一些元数据。为了做到这一点,我最终使用了一个CursorJoiner来连接ID上的c_拇指和c_图像。唯一的问题是,CursorJoiner要求输入的游标已经在连接

我正在为Android写一个“画廊类型”的应用程序。在“主活动”中,我有一个GridView,我想用设备上照片的缩略图加载/填充它。因此,我编写了一个ContentProvider,其中query方法从MediaStore.Media.Thumbnails返回一个游标

但是,我还想显示MediaStore.Media.Images中的一些元数据。为了做到这一点,我最终使用了一个CursorJoiner来连接ID上的c_拇指和c_图像。唯一的问题是,CursorJoiner要求输入的游标已经在连接键(ID)上按升序排序(排序)。我想要的是最新的照片在上面,但有没有办法排序现有的(已经加载)光标

除了CursorJoiner,也许我可以在SQL中进行连接?它是 可以加入MediaStore.Images.Media和 一次查询中的MediaStore.Images.Thumbnails(如何工作)

//将投影拆分为MediaStore和MediaStore.Thumbs部分
ArrayList MS_proj=新的ArrayList();
ArrayList MS_proj_thumbs=新建ArrayList();
for(字符串f:投影){
if(PhotoContract.ThumbEntry.COL_TYPES.get(f).equals(PhotoContract.TARGET_MEDIASTORE)){
MS_项目添加(f);
}否则{
MS_proj_thumbs.添加(f);
}
}
字符串[]MS_proj_thumbs_数组=新字符串[MS_proj_thumbs.size()];
MS_proj_thumbs_数组=MS_proj_thumbs.toArray(MS_proj_thumbs_数组);
//将_ID列添加到Images.Media projection,用于连接
项目添加(“ID”);
字符串[]MS_proj_数组=新字符串[MS_proj.size()];
MS_项目数组=MS_项目数组(MS_项目数组);
uribaseuri;
//首先,从包含所有缩略图的MediaStore.Images.Thumbnails获取光标
baseUri=MediaStore.Images.Thumbnails.EXTERNAL\u CONTENT\u URI;
Log.v(“测试”,“拇指:订单依据”+光合同.拇指条目.列\日期);
游标c_thumbs=getContext().getContentResolver().query(baseUri,MS_proj_thumbs_数组,null,null,PhotoContract.ThumbEntry.COLUMN_IMAGE_ID);
如果(c|thumbs==null | |!c|thumbs.moveToFirst()){
Log.v(“TEST”,“MediaStore.Thumbnails游标不包含数据…”);
返回null;
}
//然后,从MediaStore.Images.Media获取光标(用于标题和描述等)
//将_ID列添加到查询
baseUri=MediaStore.Images.Media.EXTERNAL\u CONTENT\u URI;
游标c_images=getContext().getContentResolver().query(baseUri、MS_proj_数组、null、null、PhotoContract.ThumbEntry.COLUMN_IMAGE_PK);
如果(c|u images==null | |!c|u images.moveToFirst()){
Log.v(“TEST”,“MediaStore.Images”光标不包含数据…”);
返回null;
}
//加入这些并返回
//连接在图像上。\u ID=缩略图。图像\u ID
CursorJoiner joiner=新的CursorJoiner(
c_thumbs,新字符串[]{PhotoContract.ThumbEntry.COLUMN_IMAGE_ID},
c_IMAGE,新字符串[]{PhotoContract.ThumbEntry.COLUMN_IMAGE_PK}
);
MatrixCursor retCursor=新MatrixCursor(投影);
/*
使用指定的列在两个游标上进行连接。
游标必须已按升序在每个指定列上排序。
此joiner仅支持键列值的元组唯一的情况。
*/
for(CursorJoiner.Result joinerResult:joiner){
开关(joinerResult){
案例左:
//处理cursorA中的行唯一的情况
打破
案例权利:
//处理cursorB中的行唯一的情况
打破
案例二:
//具有相同键的行在两个游标中的处理情况
retCursor.addRow(新对象[]){
c_thumbs.getLong(0),//ID
c_thumbs.getString(1),//数据
c_thumbs.getLong(2),//图像id
c_images.getString(0),//title
c_images.getString(1),//desc
c_images.getLong(2)//日期
});
打破
}
}
// https://stackoverflow.com/questions/12065606/getcontentresolver-query-cause-cursorwrapperinner-warning
c_拇指闭合();
c_images.close();
返回光标;
Hah,似乎可以通过简单地按ID*(-1)(升序)排序来“欺骗”Android,使其允许降序排序的CursorJoiner:

这样就解决了我的问题;最新图片在上面

请参见此处的完整答案:

哈,似乎可以通过简单地按ID*(-1)(升序)排序来“欺骗”Android,使其允许使用降序排序的CursorJoiner

这样就解决了我的问题;最新图片在上面

在此处查看完整答案:

       // split projection into MediaStore and MediaStore.Thumbs parts
        ArrayList<String> MS_proj = new ArrayList<>();
        ArrayList<String> MS_proj_thumbs = new ArrayList<>();
        for (String f : projection) {
            if (PhotoContract.ThumbEntry.COL_TYPES.get(f).equals(PhotoContract.TARGET_MEDIASTORE)) {
                MS_proj.add(f);
            } else {
                MS_proj_thumbs.add(f);
            }
        }

        String[] MS_proj_thumbs_array = new String[MS_proj_thumbs.size()];
        MS_proj_thumbs_array = MS_proj_thumbs.toArray(MS_proj_thumbs_array);

        // add _ID column to Images.Media projection, for use in JOIN
        MS_proj.add("_ID");
        String[] MS_proj_array = new String[MS_proj.size()];
        MS_proj_array = MS_proj.toArray(MS_proj_array);

        Uri baseUri;

        // first, get cursor from MediaStore.Images.Thumbnails containing all thumbnails
        baseUri = MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI;
        Log.v("TEST", "Thumb: order by " + PhotoContract.ThumbEntry.COLUMN_DATE);
        Cursor c_thumbs = getContext().getContentResolver().query(baseUri, MS_proj_thumbs_array, null, null, PhotoContract.ThumbEntry.COLUMN_IMAGE_ID);
        if (c_thumbs == null || !c_thumbs.moveToFirst()) {
            Log.v("TEST", "MediaStore.Thumbnails cursor contains no data...");
            return null;
        }

        // then, get cursor from MediaStore.Images.Media (for TITLE and DESCRIPTION etc)
        // add _ID column to query
        baseUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        Cursor c_images = getContext().getContentResolver().query(baseUri, MS_proj_array, null, null, PhotoContract.ThumbEntry.COLUMN_IMAGE_PK);
        if (c_images == null || !c_images.moveToFirst()) {
            Log.v("TEST", "MediaStore.Images cursor contains no data...");
            return null;
        }

        // join these and return
        // the join is on images._ID = thumbnails.IMAGE_ID
        CursorJoiner joiner = new CursorJoiner(
                c_thumbs, new String[] { PhotoContract.ThumbEntry.COLUMN_IMAGE_ID },
                c_images, new String[] { PhotoContract.ThumbEntry.COLUMN_IMAGE_PK }
        );

        MatrixCursor retCursor = new MatrixCursor(projection);

        /*
        Does a join on two cursors using the specified columns.
        The cursors must already be sorted on each of the specified columns in ascending order.
        This joiner only supports the case where the tuple of key column values is unique.
        */
        for (CursorJoiner.Result joinerResult : joiner) {
            switch (joinerResult) {
                case LEFT:
                    // handle case where a row in cursorA is unique
                    break;
                case RIGHT:
                    // handle case where a row in cursorB is unique
                    break;
                case BOTH:

                    // handle case where a row with the same key is in both cursors
                    retCursor.addRow(new Object[]{
                            c_thumbs.getLong(0),  // ID
                            c_thumbs.getString(1), // data
                            c_thumbs.getLong(2), // image id
                            c_images.getString(0), // title
                            c_images.getString(1),  // desc
                            c_images.getLong(2)  // date
                    });
                    break;
            }
        }


        // https://stackoverflow.com/questions/12065606/getcontentresolver-query-cause-cursorwrapperinner-warning
        c_thumbs.close();
        c_images.close();

        return retCursor;
Cursor c_thumbs = getContext().getContentResolver().query(
                baseUri, 
                MS_proj_thumbs_array, null, null, 
                "(" + PhotoContract.ThumbEntry.COLUMN_IMAGE_ID + "*(-1))"  // NB!
       );