2012-04-20 8 views
11

tengo un Android ContentProvider que permite hacer consultas LEFT OUTER JOIN en una base de datos SQLite.esquema de Android ContentProvider URI para notificar CursorAdapters que escuchan en OUTER JOIN consultas

Supongamos en la base de datos que tengo 3 tablas, Users, Articles y Comments. El ContentProvider es algo como lo siguiente:

public class SampleContentProvider extends ContentProvider { 
    private static final UriMatcher sUriMatcher; 
    public static final String AUTHORITY = "com.sample.contentprovider"; 
    private static final int USERS_TABLE = 1; 
    private static final int USERS_TABLE_ID = 2; 
    private static final int ARTICLES_TABLE = 3; 
    private static final int ARTICLES_TABLE_ID = 4; 
    private static final int COMMENTS_TABLE = 5; 
    private static final int COMMENTS_TABLE_ID = 6; 
    private static final int ARTICLES_USERS_JOIN_TABLE = 7; 
    private static final int COMMENTS_USERS_JOIN_TABLE = 8; 

    // [...] other ContentProvider methods 

    @Override 
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { 
     String table = getTableName(uri); 

     // SQLiteWrapper is a wrapper class to manage a SQLiteHelper 
     Cursor c = SQLiteWrapper.get(getContext()).getHelper().getReadableDatabase() 
       .query(table, projection, selection, selectionArgs, null, null, sortOrder); 

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

    @Override 
    public Uri insert(Uri uri, ContentValues values) { 
     String table = getTableName(uri); 

     // SQLiteWrapper is a wrapper class to manage a SQLiteHelper 
     long id = SQLiteWrapper.get(getContext()).getHelper().getWritableDatabase() 
       .insert(table, null, values); 

     Uri itemUri = ContentUris.withAppendedId(uri, id); 
     getContext().getContentResolver().notifyChange(itemUri, null); 

     return itemUri; 
    } 

    private String getTableName(Uri uri) { 
     switch (sUriMatcher.match(uri)) { 
     case USERS_TABLE: 
     case USERS_TABLE_ID: 
      return "Users"; 

     case ARTICLES_TABLE: 
     case ARTICLES_TABLE_ID: 
      return "Articles"; 

     case COMMENTS_TABLE: 
     case COMMENTS_TABLE_ID: 
      return "Comments"; 

     case ARTICLES_USERS_JOIN_TABLE: 
      return "Articles a LEFT OUTER JOIN Users u ON (u._id = a.user_id)"; 

     case COMMENTS_USERS_JOIN_TABLE: 
      return "Comments c LEFT OUTER JOIN Users u ON (u._id = c.user_id)"; 

     default: 
      throw new IllegalArgumentException("Unknown URI " + uri); 
     } 
    } 

    static { 
     sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 
     sUriMatcher.addURI(AUTHORITY, "users", USERS_TABLE); 
     sUriMatcher.addURI(AUTHORITY, "articles", ARTICLES_TABLE); 
     sUriMatcher.addURI(AUTHORITY, "comments", COMMENTS_TABLE); 
     sUriMatcher.addURI(AUTHORITY, "users" + "/#", USERS_TABLE_ID); 
     sUriMatcher.addURI(AUTHORITY, "articles" + "/#", ARTICLES_TABLE_ID); 
     sUriMatcher.addURI(AUTHORITY, "comments" + "/#", COMMENTS_TABLE_ID); 
     sUriMatcher.addURI(AUTHORITY, "???", ARTICLES_USERS_JOIN_TABLE); // what uri here? 
     sUriMatcher.addURI(AUTHORITY, "???", COMMENTS_USERS_JOIN_TABLE); // what uri here? 
    } 
} 

¿Cuál es el mejor esquema URI para notificar a todos CursorAdapter s escucha en las consultas unidas y no unidas cada vez que inserte (o actualizar) una fila en la tabla Users?

En otras palabras, si añado o actualizar una nueva fila en una de las mesas, quiero enviar un único notificación con getContext().getContentResolver().notifyChange(itemUri, null) para que todo el CursorAdapter s escucha en cualquier consulta (USERS_TABLE, ARTICLES_USERS_JOIN_TABLE, COMMENTS_USERS_JOIN_TABLE) recibir una notificación para actualizar su contenido.

Si esto no es posible, ¿hay alguna manera alternativa de notificar a todos los observadores?

Respuesta

5

Usted puede tener Uri especial para consultar con:

sUriMatcher.addURI(AUTHORITY, "articlesusers", ARTICLES_USERS_JOIN_TABLE); 
    sUriMatcher.addURI(AUTHORITY, "commentsusers", COMMENTS_USERS_JOIN_TABLE); 

pero no puedo pensar en una manera de enviar una sola notificación. Parece que su mejor opción es enviar una notificación para cada URI que haga referencia a la tabla que se está modificando. Así que sus métodos de inserción/actualización/eliminación llamarían notifyChange varias veces dependiendo de la tabla afectada. Para los cambios en "usuarios" serían 3 notificaciones: usuarios, usuarios de artículos y usuarios de comentarios, ya que todos dependen de la tabla de "usuarios".

1

Respondido por prodaea, aquí hay otra alternativa que puede utilizar para la notificación de Uri. Esta no es una solución perfecta, pero usa solo un Uri para notificaciones.

La solución es utilizar el principal Uri sin ningún nombre de la tabla (por ejemplo: contenido: //com.example.app.provider/) como la notificación Uri en el método de consulta para ARTICLES_USERS_JOIN_TABLE y COMMENTS_USERS_JOIN_TABLE. Por lo tanto, el cursor relacionado se notificará siempre que haya cambios en cualquier tabla. Sin embargo, hay una limitación. Es decir, se notificará el cursor ARTICLES_USERS_JOIN_TABLE incluso cuando haya cambios en la tabla Articles.

Para tablas, Users' and Artículos ', puede usar su Uris específico para la notificación.

+0

manera más elegante que llamar a notifyChange después de cada inserción/actualización/eliminación como se sugiere en [respuesta de satur9nine] (http://stackoverflow.com/a/11661855/5756760)! – Joni

Cuestiones relacionadas