2012-04-20 10 views
11

Tôi có Android ContentProvider cho phép thực hiện LEFT OUTER JOIN truy vấn trên cơ sở dữ liệu SQLite.Đề án URI Android ContentProvider để thông báo cho CursorAdapters nghe trên các truy vấn OUTER JOIN

Giả sử trong cơ sở dữ liệu tôi có 3 bảng, Users, ArticlesComments. Các ContentProvider là một cái gì đó như sau:

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

giao thức URI tốt nhất để thông báo cho tất cả CursorAdapter s nghe trên các truy vấn tham gia và không tham gia mỗi khi tôi chèn (hoặc cập nhật) một hàng trong bảng Users là gì?

Nói cách khác, nếu tôi thêm hoặc cập nhật hàng mới trong một trong các bảng, tôi muốn gửi một đơn thông báo với getContext().getContentResolver().notifyChange(itemUri, null) để tất cả các CursorAdapter s nghe trên bất kỳ truy vấn (USERS_TABLE, ARTICLES_USERS_JOIN_TABLE, COMMENTS_USERS_JOIN_TABLE) nhận được thông báo để cập nhật nội dung của họ.

Nếu điều này là không thể, có cách nào khác để thông báo cho tất cả các nhà quan sát không?

Trả lời

5

Bạn có thể có đặc biệt của Uri để truy vấn với:

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

Nhưng tôi không thể nghĩ ra một cách để gửi một thông báo. Có vẻ như lựa chọn tốt nhất của bạn là gửi thông báo cho mỗi Uri đề cập đến bảng đang được sửa đổi. Vì vậy, phương pháp chèn/cập nhật/xóa của bạn sẽ gọi notifyChange nhiều lần tùy thuộc vào bảng bị ảnh hưởng. Đối với những thay đổi đối với "người dùng", nó sẽ là 3 thông báo - người dùng, người viết bài và người nhận xét - vì tất cả đều phụ thuộc vào bảng "người dùng".

1

Được trả lời bởi prodaea, dưới đây là một giải pháp thay thế khác mà bạn có thể sử dụng để thông báo cho Uri. Đây không phải là một giải pháp hoàn hảo, nhưng nó chỉ sử dụng một Uri để thông báo.

Giải pháp là sử dụng Uri chính mà không có bất kỳ tên bảng nào (ví dụ: content: //com.example.app.provider/) làm thông báo Uri trong phương thức truy vấn cho ARTICLES_USERS_JOIN_TABLECOMMENTS_USERS_JOIN_TABLE. Vì vậy, con trỏ liên quan sẽ được thông báo bất cứ khi nào có sự thay đổi trong bất kỳ bảng nào. Có một giới hạn mặc dù. Tức là, ARTICLES_USERS_JOIN_TABLE con trỏ sẽ được thông báo ngay cả khi có thay đổi trong bảng Articles.

Đối với các bảng, Users' and Bài viết ', bạn có thể sử dụng Uris cụ thể của chúng để thông báo.

+0

cách thanh lịch hơn gọi callingChange sau mỗi lần chèn/cập nhật/xóa như được đề xuất trong câu trả lời của [satur9nine] (http://stackoverflow.com/a/11661855/5756760)! – Joni