loadercallbacks android sqlite

android - loadercallbacks - cómo usar la consulta de combinación en CursorLoader cuando su constructor no lo admite



sqlite (2)

Estoy teniendo dos tablas con relación 1: n, estoy usando el proveedor de contenido y el cursorloader.

¿Cómo haría una consulta de combinación para trabajar con el cargador de cursor? Podría hackearlo de alguna manera con rawSql dentro del proveedor de contenido, pero la forma de hacerlo en el constructor del cargador de cursor me supera.

Muchas gracias !

CursorLoader (Contexto contextual, Uri uri, String [] proyección, String selection, String [] selectionArgs, String sortOrder)

Cómo consultar para unirse cuando Uri solo podía señalar una tabla


El Uri no apunta a ninguna tabla. Señala lo que sea que quieras señalar.

Imaginemos que sus dos tablas son Customer y Order . Un cliente puede tener muchos pedidos. Desea ejecutar una consulta para obtener todos los pedidos pendientes ... pero desea unirse a algunas columnas relacionadas con los clientes que necesitará, como el nombre del cliente.

Vamos a pretender que ya tienes content://your.authority.goes.here/customer y content://your.authority.goes.here/order definida para consultar únicamente esas tablas.

Tienes dos opciones:

  1. Agregue la combinación del nombre para mostrar del cliente en su /order Uri . Tener otra columna disponible probablemente no afectará a ningún consumidor existente del proveedor (aunque las pruebas siempre son una buena idea). Esto es lo que hace ContactsContract : se une en algunas columnas base, como el nombre del contacto, en casi todas las consultas de todas las tablas.

  2. Crear content://your.authority.goes.here/orderWithCust que hace la misma consulta básica que hace /order , pero contiene su unión. En este caso, puede hacer que insert() , update() y delete() arrojen algún tipo de RuntimeException para recordarle que no debe modificar los datos usando /orderWithCust como Uri .

Al final, el diseño de un sistema ContentProvider Uri es similar al diseño del sistema URL de un servicio web REST. En ambos casos, la unión debe hacerse en el lado proveedor / servidor, por lo que es posible que deba romper la línea de base de una tabla a una URL para ofrecer algunas combinaciones útiles.


Encontré una solución usando subclases de ContentProvider. Digamos que tiene la tabla tblA y otra tabla tblB. Recomiendo crear dos clases "AContentProvider" y "BContentProvider". Lo más importante es asegurarse de que ambas tablas estén configuradas en la misma base de datos.

La parte principal de la solución es anular ContentProvider.query () en ContentProvider al que llamará desde su CursorLoader: el URI decide cuál es:

@Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sort) { SQLiteQueryBuilder qb = new SQLiteQueryBuilder(); qb.setTables( "tblA LEFT JOIN tblB" + " ON (" + "tblA.b_id" + " = " + "tblB.id" + ")" ); ... // Content of projection is set by CursorLoader // usually in an Activity that implements LoaderManager.LoaderCallbacks<> Cursor c = qb.query( database, projection, selection, selectionArgs, groupBy, having, orderBy ); ... return c; }

Como puede ver, JOIN se hace en setTables () . Con la proyección , asegúrese de que solo muestra las columnas que realmente necesita y, sobre todo, no tiene columnas duplicadas, como "id" en ambas tablas:

final String[] projection = new String[] { "tblA.*", "tblB.columnThatOnlyBHas" };

Utilice la anulación e intente realizar todo el trabajo en las subclases que pueda; por ejemplo: todos mis métodos de consulta anulados () llaman a setNotificationUri () para notificar a ContentResolver si el resultado del cursor establece cambios .:

c.setNotificationUri(getContext().getContentResolver(), uri);