How to use two Cursors and CursorJoiner in LoaderManager in android

☆樱花仙子☆ 提交于 2019-11-30 08:53:13

Use two loaders, one for each cursor. When either one finishes loading, call another method that will join them if both have loaded.

// Loader IDs. You could also generate unique R.id values via XML
private static final int LOADER_ID_CURSOR_1 = 1;
private static final int LOADER_ID_CURSOR_2 = 2;

private Cursor cursor1 = null;
private Cursor cursor2 = null;

// return loader for cursor 1
private CusorLoader getCursor1Loader() {
    Uri uri = Uri.parse(abc);
    String[] select = abc; 
    String where = abc;
    String[] whereArgs = abc;
    String sortOrder = abc;
    return new CursorLoader(uri, select, where, whereArgs, sortOrder);
}

// return loader for cursor 2
private CusorLoader getCursor2Loader() {
    // same as above but with different values
    return new CursorLoader(uri, select, where, whereArgs, sortOrder);
}

// to start loading, ...
LoaderManager lm = getLoaderManager();
lm.initLoader(LOADER_ID_CURSOR_1, null, this);
lm.initLoader(LOADER_ID_CURSOR_2, null, this);

// LoaderCallbacks implementations
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
    switch(id) {
    case LOADER_ID_CURSOR_1:
        return getCursor1Loader();
    case LOADER_ID_CURSOR_2:
        return getCursor2Loader();
    }
}

@override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
    switch(loader.getId()) {
    case LOADER_ID_CURSOR_1:
        cursor1 = data;
        joinCursors();
        break;
    case LOADER_ID_CURSOR_2:
        cursor2 = data;
        joinCursors();
        break;
    }
}

private void joinCursors() {
    if (cursor1 != null && cursor2 != null) {
        // use CursorJoiner here
    }
}

I have written a class which loads two different Cursors using the LoaderManager and returns the CursorJoiner.Result objects so you can handle the join. There is not much to say about this code, if something is unclear or you have any questions just ask in the comments!

public class JoinLoader {

    public interface JoinHandler {
        public void onHandleJoin(CursorJoiner.Result result);
    }

    private static final int LOADER_ONE = 0;
    private static final int LOADER_TWO = 1;

    private final LoaderCallbackImpl callbackOne;
    private final LoaderCallbackImpl callbackTwo;

    private final Context context;
    private final LoaderManager loaderManager;

    private Cursor cursorOne;
    private Cursor cursorTwo;

    private String[] leftColumns;
    private String[] rightColumns;

    private JoinHandler joinHandler;

    private JoinLoader(Activity activity) {
        this.context = activity;
        this.loaderManager = activity.getLoaderManager();
        this.callbackOne = new LoaderCallbackImpl(activity, new LoaderCallbackImpl.FinishedListener() {
            @Override
            public void onFinished(Cursor data) {
                cursorOne = data;
                handleSuccess();
            }
        });
        this.callbackTwo = new LoaderCallbackImpl(activity, new LoaderCallbackImpl.FinishedListener() {
            @Override
            public void onFinished(Cursor data) {
                cursorTwo = data;
                handleSuccess();
            }
        });
    }

    public void start() {
        this.cursorOne = null;
        this.cursorTwo = null;
        this.loaderManager.initLoader(LOADER_ONE, null, this.callbackOne);
        this.loaderManager.initLoader(LOADER_TWO, null, this.callbackTwo);
    }

    public void setJoinOn(String[] leftColumns, String[] rightColumns) {
        this.leftColumns = leftColumns;
        this.rightColumns = rightColumns;
    }

    private void handleSuccess() {
        if(this.joinHandler != null && this.cursorOne != null && this.cursorTwo != null) {
            CursorJoiner joiner = new CursorJoiner(this.cursorOne, this.leftColumns, this.cursorTwo, this.rightColumns);
            for (CursorJoiner.Result result : joiner) {
                this.joinHandler.onHandleJoin(result);
            }
            this.cursorOne.close();
            this.cursorTwo.close();
        }
    }

    public void setJoinHandler(JoinHandler joinHandler) {
        this.joinHandler = joinHandler;
    }

    public void setFirstQuery(Uri uri, String[] projection, String selection, String[] selectionArgs, String orderBy) {
        this.callbackOne.setQuery(uri, projection, selection, selectionArgs, orderBy);
    }

    public void setSecondQuery(Uri uri, String[] projection, String selection, String[] selectionArgs, String orderBy) {
        this.callbackTwo.setQuery(uri, projection, selection, selectionArgs, orderBy);
    }

    private static class LoaderCallbackImpl implements LoaderManager.LoaderCallbacks<Cursor> {

        public interface FinishedListener {
            public void onFinished(Cursor data);
        }

        private final Context context;
        private final FinishedListener finishedListener;

        private Uri uri;
        private String[] projection;
        private String selection;
        private String[] selectionArgs;
        private String orderBy;

        private boolean finished = false;

        private LoaderCallbackImpl(Context context, FinishedListener listener) {
            this.context = context;
            this.finishedListener = listener;
        }

        @Override
        public Loader<Cursor> onCreateLoader(int id, Bundle args) {
            this.finished = false;
            return new CursorLoader(context, uri, projection, selection, selectionArgs, orderBy);
        }

        @Override
        public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
            this.finished = true;
            if(this.finishedListener != null) {
                this.finishedListener.onFinished(data);
            }
        }

        @Override
        public void onLoaderReset(Loader<Cursor> loader) {

        }

        public void setQuery(Uri uri, String[] projection, String selection, String[] selectionArgs, String orderBy) {
            this.uri = uri;
            this.projection = projection;
            this.selection = selection;
            this.selectionArgs = selectionArgs;
            this.orderBy = orderBy;
        }

        public boolean isFinished() {
            return finished;
        }
    }
}

I tested the class and it seems to work as expected. You can use it like this:

JoinLoader loader = new JoinLoader(activity);
loader.setFirstQuery(firstUri, firstProjection, firstSelection, firstSelectionArgs, firstOrderBy);
loader.setSecondQuery(secondUri, secondProjection, secondSelection, secondSelectionArgs, secondOrderBy);
loader.setJoinOn(leftColumns, rightColumns);
loader.setJoinHandler(new JoinLoader.JoinHandler() {
    @Override
    public void onHandleJoin(CursorJoiner.Result result) {
        switch (result) {
            case LEFT:
                ...
                break;

            case RIGHT:
                ...
                break;

            case BOTH:
                ...
                break;
        }
    }
});
loader.start();

I hope I could help you, if you have any further questions please feel free to ask!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!