2012-04-20 5 views
11

Ich habe ein Android ContentProvider, die LEFT OUTER JOIN Abfragen in einer SQLite-Datenbank ermöglicht. In der Datenbank habe ich 3 Tabellen, Users, Articles und Comments. Die ContentProvider ist so etwas wie die folgende:Android ContentProvider URI-Schema zu Benachrichtigen CursorAdapters hören auf OUTER JOIN Abfragen

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

Was ist das beste URI-Schema all CursorAdapter s Hören zu dem verbundenen und nicht verbundenen Abfragen I (oder Update), um eine Zeile in der Tabelle einfügen Users jedes Mal zu informieren?

Mit anderen Worten, wenn ich eine neue Zeile in einen der Tabellen hinzufügen oder aktualisieren, ich will mit getContext().getContentResolver().notifyChange(itemUri, null) eine einzelnen Benachrichtigung senden, so dass alle CursorAdapter s Hören auf jeder Abfrage (USERS_TABLE, ARTICLES_USERS_JOIN_TABLE, COMMENTS_USERS_JOIN_TABLE) erhalten eine Benachrichtigung, um ihren Inhalt zu aktualisieren.

Wenn dies nicht möglich ist, gibt es eine alternative Möglichkeit, alle Beobachter zu benachrichtigen?

Antwort

5

Sie können spezielle Urner haben abfragen mit:

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

Aber ich kann nicht denken Sie an einen Weg, um eine einzige Mitteilung zu senden. Es scheint Ihre beste Wahl zu sein, eine Benachrichtigung für jeden Uri zu senden, der sich auf die Tabelle bezieht, die geändert wird. Daher würden Ihre Methoden insert/update/delete abhängig von der betroffenen Tabelle mehrfach notifyChange aufrufen. Für Änderungen an "Benutzern" wären es 3 Benachrichtigungen - Benutzer, Artikelbenutzer und Kommentarebenutzer - da sie alle von der "Benutzer" -Tabelle abhängen.

1

Wie beantwortet von prodaea, hier ist eine andere Alternative, die Sie für die Benachrichtigung Uri verwenden können. Dies ist keine perfekte Lösung, aber es verwendet nur einen Uri für die Benachrichtigung.

Die Lösung besteht darin, die Haupt-Uri ohne Tabellennamen (z. B. content: //com.example.app.provider/) als Benachrichtigungs-Uri in der Abfragemethode für ARTICLES_USERS_JOIN_TABLE und COMMENTS_USERS_JOIN_TABLE zu verwenden. Daher wird der zugehörige Cursor benachrichtigt, sobald eine Tabelle geändert wird. Es gibt jedoch eine Einschränkung. Das heißt, ARTICLES_USERS_JOIN_TABLE Cursor wird benachrichtigt, auch wenn es eine Änderung in Articles Tabelle gibt.

Für Tabellen, Users' and Artikel können Sie ihre spezifischen Uris für die Benachrichtigung verwenden.

+0

Weise eleganter als NotifyChange nach jedem Einfügen/Aktualisieren/Löschen wie in [satur9nine's answer] (http://stackoverflow.com/a/11661855/5756760) vorgeschlagen aufrufen! – Joni