Querying the MediaStore: Joining thumbnails and images (on ID)

前端 未结 3 780
情深已故
情深已故 2021-02-15 12:38

I\'m working on a \"photo gallery\"-type app for Android. It started as a Final Project for the Developing Android Apps at Udacity, so it\'s overall structure (activities, conte

3条回答
  •  青春惊慌失措
    2021-02-15 13:09

    Here is my test case, which demonstrates the lack of support in CursorJoiner for descending ordered cursors. This, however, is documented specifically in the CursorJoiner source code, so I'm not trying to critize but merely show how this can be circumvented (or hacked).

    The test case shows how the assumption of ascending ordering makes the need for "flipping", or reversing, all of the choices made by the CursorJoiner (comparator result, incrementation of cursors, etc). What I'd really like to try next is to modify the CursorJoiner class directly, to try to add support for DESC ordering.

    Please note that it seems the part about ordering by ID*(-1) maybe is not strictly necessary for this to work. In the following example, I did not negate the ID columns (plain DESC ordering, not "pseudo-ASC" with negative sequences), and it still works.

    Test case

    String[] colA = new String[] { "_id", "data", "B_id" };
    String[] colB = new String[] { "_id", "data" };
    
    MatrixCursor cursorA = new MatrixCursor(colA);
    MatrixCursor cursorB = new MatrixCursor(colB);
    
    // add 4 items to cursor A, linked to cursor B
    // the data is ordered DESCENDING
    // all cases, LEFT/RIGHT/BOTH, are included
    cursorA.addRow(new Object[] { 5, "Item A", 1004 });  // BOTH
    cursorA.addRow(new Object[] { 4, "Item B", 1003 });  // LEFT
    cursorA.addRow(new Object[] { 3, "Item C", 1002 });  // BOTH
    cursorA.addRow(new Object[] { 2, "Item D", 1001 });  // LEFT
    cursorA.addRow(new Object[] { 1, "Item E", 1000 });  // BOTH
    cursorA.addRow(new Object[] { 0, "Item F", 500 });  // LEFT
    
    // similarily for cursorB (DESC)
    cursorB.addRow(new Object[] { 1004, "X" });   // BOTH
    cursorB.addRow(new Object[] { 1002, "Y" });   // BOTH
    cursorB.addRow(new Object[] { 999,  "Z" });    // RIGHT
    cursorB.addRow(new Object[] { 998,  "S" });    // RIGHT
    cursorB.addRow(new Object[] { 900,  "A" });    // RIGHT
    cursorB.addRow(new Object[] { 1000, "G" });   // BOTH
    
    // join these on ID
    CursorJoiner cjoiner = new CursorJoiner(
            cursorA, new String[] { "B_id" },   // left = A
            cursorB, new String[] { "_id" }     // right = B
    );
    
    // enable workaround
    boolean desc = true;
    
    int count = 0;
    for (CursorJoiner.Result joinerResult : cjoiner) {
        Log.v("TEST", "Processing (left)=" + (cursorA.isAfterLast() ? "" : cursorA.getLong(2))
                    + " / (right)=" + (cursorB.isAfterLast() ? "" : cursorB.getLong(0)));
    
         // flip the CursorJoiner.Result (unless Result.BOTH, or either cursor is exhausted)
        if (desc && joinerResult != CursorJoiner.Result.BOTH
                 && !cursorB.isAfterLast() && !cursorA.isAfterLast())
            joinerResult = (joinerResult == CursorJoiner.Result.LEFT ? CursorJoiner.Result.RIGHT : CursorJoiner.Result.LEFT);
    
        switch (joinerResult) {
            case LEFT:
                // handle case where a row in cursorA is unique
                Log.v("TEST", count + ") join LEFT. cursorA is unique");
    
                if (desc) {
                    // compensate cursor increments
                    if (!cursorB.isAfterLast()) cursorB.moveToPrevious();
                    if (!cursorA.isLast()) cursorA.moveToNext();
                }
                break;
    
            case RIGHT:
                Log.v("TEST", count + ") join RIGHT. cursorB is unique");
                // handle case where a row in cursorB is unique
    
                if (desc) {
                    if (!cursorB.isLast()) cursorB.moveToNext();
                    if (!cursorA.isAfterLast()) cursorA.moveToPrevious();
                }
                break;
    
            case BOTH:
                Log.v("TEST", count + ") join BOTH: " + cursorA.getInt(0) + "," + cursorA.getString(1) + "," + cursorA.getInt(2) + "/" + cursorB.getInt(0) + "," + cursorB.getString(1));
                // handle case where a row with the same key is in both cursors
                break;
    
        }
    
        count++;
    }
    Log.v("TEST", "Join done!");
    

    and the output:

    V/TEST: Processing (left)=5 / (right)=1004
    V/TEST: 0) join BOTH: 4,Item A,1004/1004,X
    V/TEST: Processing (left)=4 / (right)=1002
    V/TEST: 1) join LEFT. cursorA is unique
    V/TEST: Processing (left)=3 / (right)=1002
    V/TEST: 2) join BOTH: 2,Item C,1002/1002,Y
    V/TEST: Processing (left)=2 / (right)=999
    V/TEST: 3) join RIGHT. cursorB is unique
    V/TEST: Processing (left)=2 / (right)=998
    V/TEST: 4) join RIGHT. cursorB is unique
    V/TEST: Processing (left)=2 / (right)=900
    V/TEST: 5) join RIGHT. cursorB is unique
    V/TEST: Processing (left)=2 / (right)=1000
    V/TEST: 6) join LEFT. cursorA is unique
    V/TEST: Processing (left)=1 / (right)=1000
    V/TEST: 7) join BOTH: 0,Item D,1000/1000,F
    V/TEST: Processing (left)=0 / (right)=---
    V/TEST: 8) join LEFT. cursorA is unique
    V/TEST: Join done!
    

提交回复
热议问题