Cómo utilizar dos cursores y CursorJoiner en LoaderManager en android

Tengo un ContentProvider , está teniendo dos tablas 1. OnlineContacts 2. AllContacts . Entonces tengo un método en el que estoy consultando ambas tablas y obteniendo sus cursors resultantes por separado. Y luego unirse a ellos utilizando CursorJoiner y hacer una lista de Contacts . Pasando esta lista a mi CustomAdapter extending BaseAdapter , estoy poblando mi listview . Me gusta :

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

Y aquí está mi 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; } } 

Ahora, necesito hacerlo usando LoaderManager . Sé, hasta cierto punto, la aplicación de la misma. Lo sé, el onCreateLoader actúa como:

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

Y en OnCreate , si utilizo MyCursorAdapter extending CursorAdapter , hacemos algo como:

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

Ahora, necesito hacer es cómo puedo lograr la implementación antedicha usando LoaderManager . No sabía cómo preguntar eso por qué es demasiado explicativo.

Utilice dos cargadores, uno para cada cursor. Cuando uno termine de cargar, llame a otro método que se unirá a ellos si ambos han cargado.

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

He escrito una clase que carga dos Cursors diferentes usando LoaderManager y devuelve los objetos CursorJoiner.Result para que pueda manejar la unión. No hay mucho que decir sobre este código, si algo no está claro o si tiene alguna pregunta solo pregunte en los comentarios!

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

He probado la clase y parece que funciona como se esperaba. Puedes usarlo así:

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

¡Espero poder ayudarle, si usted tiene alguna otra pregunta por favor no dude en preguntar!

  • ¿Cómo pasar de managedQuery a LoaderManager / CursorLoader?
  • Cargadores en Android Honeycomb
  • Matrixcursor con proveedor de contenido no-db
  • ¿Cuál es el alcance de un LoaderManager?
  • ¿Qué CursorAdapter tengo que usar?
  • Loader y LoaderManager - ¿Cómo determinar si un cargador actual está activo y en ejecución?
  • Paquete de Compatibilidad con Android y getLoaderManager ()
  • ¿Cuál es el alcance de LoaderManager?
  • Cargadores y OnLoaderReset Android
  • Error: java.lang.NullPointerException en android.support.v4.content.Loader
  • AsyncTaskLoader onLoadFinished con un cambio de tarea y configuración pendiente
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.