如何在android中的LoaderManager中使用两个游标和CursorJoiner

我有一个ContentProvider ,它有两个表1. OnlineContacts 2. AllContacts 。 然后我有一个方法,我在查询两个表,并分别得到他们的结果cursors 。 然后使用CursorJoiner join他们并制作Contacts列表。 将此列表传递给我的CustomAdapter extending BaseAdapter ,我填充我的listview 。 喜欢 :

 public static List<Contact> getContacts(Context context){ List<Contact> contactList = new ArrayList<Contact>(); // Getting First Cursor String URL = xyz; Uri baseUri1 = Uri.parse(URL); String[] select = xyz; String where =xyz; Cursor cursor = context.getContentResolver().query(baseUri1, select, where, null, "pid"); // Getting 2nd Cursor Uri baseUri = xyz; String[] projection =xyz; String selection =xyz; String[] selectionArgs = null; String sortOrder = xyz; Cursor mCursor= context.getContentResolver().query(baseUri, projection, selection, selectionArgs, sortOrder); // Joinging Both Cursors CursorJoiner joiner = new CursorJoiner(cursor, new String[] {MyContentProvider.PHONE_ID} , mCursor, new String[] {MyContentProvider.Phone._ID}); for (CursorJoiner.Result joinerResult : joiner) { Contact cont = new Contact(); 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 case BOTH: // handle case where a row with the same key is in both cursors cont.setID(xyz); cont.setName(xyz); cont.setPhoneNumber(xyz); cont.setStatus("0"); contactList.add(cont); break; } } mCursor.close(); cursor.close(); return contactList; } 

这里是我的CustomAdapter

 private class CustomAdapter extends BaseAdapter { List<Contact> contactsList ; public CustomAdapter(List<Contact> contactsList){ this.contactsList = contactsList; } public List<Contact> contacts() { return this.contactsList; } @Override public int getCount() { return contactsList.size(); } @Override public Contact getItem(int arg0) { return contactsList.get(arg0); } @Override public long getItemId(int arg0) { return arg0; } @Override public View getView(int position, View view, ViewGroup viewGroup) { SimpleViewHolder viewHolder; if(view==null) { LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); view = inflater.inflate(R.layout.list_item, viewGroup,false); viewHolder = new SimpleViewHolder(view); view.setTag(viewHolder); } viewHolder = (SimpleViewHolder) view.getTag(); TextView contName = (TextView) viewHolder.get(R.id.nameText); ImageView image = (ImageView) viewHolder.get(R.id.contact_image); Contact contact = contactsList.get(position); image.setBackgroundResource(R.drawable.person_empty_offline); contName.setText(contact.getName()); return view; } } 

现在,我需要使用LoaderManager来做到这一点。 我知道,在某种程度上,它的实施。 我知道, onCreateLoader行为如下所示:

  public Loader<Cursor> onCreateLoader(int id, Bundle args) { Uri baseUri = xyz; String[] projection = xyz; String selection = xyz; String[] selectionArgs = null; String sortOrder = xyz; return new CursorLoader(getActivity(), baseUri, projection, selection, selectionArgs, sortOrder); } 

而在OnCreate ,如果我使用MyCursorAdapter extending CursorAdapter ,我们可以这样做:

 mAdapter = new MyCursorAdapter(getActivity(), null, 0); setListAdapter(mAdapter); getLoaderManager().initLoader(0, null, this); 

现在,我需要做的是如何使用LoaderManager实现上述实现。 我不知道怎么问这个,为什么它太说明了。

Solutions Collecting From Web of "如何在android中的LoaderManager中使用两个游标和CursorJoiner"

使用两个装载机,每个游标一个。 当任何一个完成加载,调用另一个方法,将join他们,如果两个已经加载。

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

我已经写了一个类,使用LoaderManager加载两个不同的Cursors ,并返回CursorJoiner.Result对象,以便处理连接。 关于这个代码没什么可说的,如果有什么不清楚的地方,或者在评论中有任何问题就问!

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

我testing了这个class级,它似乎按预期工作。 你可以像这样使用它:

 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(); 

我希望我能帮助你,如果你有任何问题,请随时询问!