Filtering a cursor the right way?

前端 未结 3 1559
我在风中等你
我在风中等你 2020-12-04 22:41

At the moment I need to filter a Cursor/CursorAdapter to only show rows that match a specific condition in the ListView. I don\'t want to requery the db all the time. I just

3条回答
  •  眼角桃花
    2020-12-04 23:12

    UPDATE:

    I have rewritten the source and my employer has made it available as open source software: https://github.com/clover/android-filteredcursor

    You don't need to override all the move methods in CursorWrapper, you do need to override a bunch though due to the design of the Cursor interface. Let's pretend you want to filter out row #2 and #4 of a 7 row cursor, make a class that extends CursorWrapper and override these methods like so:

    private int[] filterMap = new int[] { 0, 1, 3, 5, 6 };
    private int mPos = -1;
    
    @Override
    public int getCount() { return filterMap.length }
    
    @Override
    public boolean moveToPosition(int position) {
        // Make sure position isn't past the end of the cursor
        final int count = getCount();
        if (position >= count) {
            mPos = count;
            return false;
        }
    
        // Make sure position isn't before the beginning of the cursor
        if (position < 0) {
            mPos = -1;
            return false;
        }
    
        final int realPosition = filterMap[position];
    
        // When moving to an empty position, just pretend we did it
        boolean moved = realPosition == -1 ? true : super.moveToPosition(realPosition);
        if (moved) {
            mPos = position;
        } else {
            mPos = -1;
        }
        return moved;
    }
    
    @Override
    public final boolean move(int offset) {
        return moveToPosition(mPos + offset);
    }
    
    @Override
    public final boolean moveToFirst() {
        return moveToPosition(0);
    }
    
    @Override
    public final boolean moveToLast() {
        return moveToPosition(getCount() - 1);
    }
    
    @Override
    public final boolean moveToNext() {
        return moveToPosition(mPos + 1);
    }
    
    @Override
    public final boolean moveToPrevious() {
        return moveToPosition(mPos - 1);
    }
    
    @Override
    public final boolean isFirst() {
        return mPos == 0 && getCount() != 0;
    }
    
    @Override
    public final boolean isLast() {
        int cnt = getCount();
        return mPos == (cnt - 1) && cnt != 0;
    }
    
    @Override
    public final boolean isBeforeFirst() {
        if (getCount() == 0) {
            return true;
        }
        return mPos == -1;
    }
    
    @Override
    public final boolean isAfterLast() {
        if (getCount() == 0) {
            return true;
        }
        return mPos == getCount();
    }
    
    @Override
    public int getPosition() {
        return mPos;
    }
    

    Now the interesting part is creating the filterMap, that's up to you.

提交回复
热议问题