加入光标和排序光标

2023-09-05 04:43:56 作者:爱与恨总是一线之隔

我在写一个画廊式的应用程序为Android。在主活动,我有我想要加载/填充从设备上的照片缩略图的GridView控件。所以,我写了一个ContentProvider的,那里的查询方法返回一个光标从MediaStore.Media.Thumbnails。

不过,我也希望显示MediaStore.Media.Images一些元数据。为了做到这一点,我结束了使用一个CursorJoiner加入c_thumbs和c_images的ID。唯一的问题与此,是CursorJoiner需要输入光标已经进行排序(订购)上的连接键(ID),按升序排列。我要的是在上面最新的照片,但有这样一个现有(已加载)光标排序?

       

另外,以CursorJoiner,也许我可以做的加入SQL?是吗     可能加盟MediaStore.Images.Media和     在一个查询MediaStore.Images.Thumbnails(以及如何将这项工作)?

        

Apparently,这是不可能的

  //分割投影到MediaStore和MediaStore.Thumbs件
        ArrayList的<字符串> MS_proj =新的ArrayList<>();
        ArrayList的<字符串> MS_proj_thumbs =新的ArrayList<>();
        对于(字符串型F:投影){
            如果(PhotoContract.ThumbEntry.COL_TYPES.get(F).equals(PhotoContract.TARGET_MEDIASTORE)){
                MS_proj.add(F);
            } 其他 {
                MS_proj_thumbs.add(F);
            }
        }

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

        //添加_ID列Images.Media投影,用于JOIN
        MS_proj.add(_编号);
        的String [] MS_proj_array =新的String [MS_proj.size()];
        MS_proj_array = MS_proj.toArray(MS_proj_array);

        乌里基本URI;

        //首先,让光标从包含所有缩略图MediaStore.Images.Thumbnails
        基本URI = MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI;
        Log.v(TEST,拇指:为了通过+ PhotoContract.ThumbEntry.COLUMN_DATE);
        光标c_thumbs =的getContext()getContentResolver()查询(基本URI,MS_proj_thumbs_array,NULL,NULL,PhotoContract.ThumbEntry.COLUMN_IMAGE_ID)。
        如果(c_thumbs == NULL ||!c_thumbs.moveToFirst()){
            Log.v(TEST,MediaStore.Thumbnails光标不包含任何数据。);
            返回null;
        }

        //然后,让光标从MediaStore.Images.Media(对标题和描述等)
        //添加_ID列查询
        基本URI = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        光标c_images =的getContext()getContentResolver()查询(基本URI,MS_proj_array,NULL,NULL,PhotoContract.ThumbEntry.COLUMN_IMAGE_PK)。
        如果(c_images == NULL ||!c_images.moveToFirst()){
            Log.v(TEST,MediaStore.Images光标不包含任何数据。);
            返回null;
        }

        //加入这些与回报
        //连接是在images._ID = thumbnails.IMAGE_ID
        CursorJoiner木匠=新CursorJoiner(
                c_thumbs,新的String [] {} PhotoContract.ThumbEntry.COLUMN_IMAGE_ID,
                c_images,新的String [] {} PhotoContract.ThumbEntry.COLUMN_IMAGE_PK
        );

        MatrixCursor retCursor =新MatrixCursor(投影);

        / *
        做了一个连接上使用指定的列两个光标。
        在游标必须已经进行排序每个升序排列指定的列。
        这个木匠只支持其中key列值的元组是唯一的案例。
        * /
        对于(CursorJoiner.Result joinerResult:木匠){
            开关(joinerResult){
                情况下左:
                    //处理情况下,一排CursorA软键是独一无二的
                    打破;
                案例RIGHT:
                    //处理情况下,一排CursorB软键是独一无二的
                    打破;
                如果两个:

                    //处理的情况下连续使用相同的关键是在两个光标
                    retCursor.addRow(新对象[] {
                            c_thumbs.getLong(0),// ID
                            c_thumbs.getString(1),//数据
                            c_thumbs.getLong(2),//图像标识
                            c_images.getString(0),//标题
                            c_images.getString(1),//递减
                            c_images.getLong(2)//日期
                    });
                    打破;
            }
        }


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

        返回retCursor;
 

解决方案

哈,似乎人们可以欺骗的Andr​​oid成允许 CursorJoiner由大到小排序简单地通过ID *订购( - 1) (升序):

 光标c_thumbs =的getContext()。getContentResolver()查询(
                基本URI,
                MS_proj_thumbs_array,NULL,NULL,
                (+ PhotoContract.ThumbEntry.COLUMN_IMAGE_ID +*( -  1))//注意!
       );
 

这样解决我的问题;最新的图像之上!

点击这里查看完整的答案: Querying在MediaStore:加入缩略图和图像(的ID)

为什么在Excel中有时进行排序时只是光标所在的一列排序了而其他列却不变呢

I'm writing a "gallery-type" app for Android. In the "master activity", I have a GridView which I want to load/fill with thumbnails from photos on the device. So I've written a ContentProvider, where the query method returns a cursor from MediaStore.Media.Thumbnails.

However, I also want to display some meta data from MediaStore.Media.Images. In order to do this, I ended up using a CursorJoiner to join c_thumbs and c_images on ID. Only problem with this, is that CursorJoiner requires the input cursors to already be sorted (ordered) on the join key (ID), in ascending order. What I want is newest photos on top, but is there way to sort an existing (already loaded) cursor?

Alternatively to CursorJoiner, maybe I could do the join in SQL? Is it possible to join MediaStore.Images.Media and MediaStore.Images.Thumbnails in one query (and how would that work)?

Apparently, that's not possible

       // 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;
            }
        }


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

        return retCursor;

解决方案

Hah, it seems one can "trick" Android into allowing CursorJoiner with descending sort by simply ordering by ID*(-1) (ascending):

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

So that solves my problem; newest images on top!

See full answer here: Querying the MediaStore: Joining thumbnails and images (on ID)