2012-04-20 13 views
11

मेरे पास एक एंड्रॉइड ContentProvider है जो SQLite डेटाबेस पर LEFT OUTER JOIN क्वेरी करने की अनुमति देता है।एंड्रॉइड कंटेंटप्रोवाइडर यूआरआई योजना को कर्सर एडाप्टर को सूचित करने के लिए बाहरी जॉइन प्रश्नों पर सुनना

मान लें कि डेटाबेस में मेरे पास 3 टेबल, Users, Articles और Comments है। ContentProvider की तरह कुछ है निम्नलिखित:

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

सबसे अच्छा यूआरआई में शामिल हो गए और गैर में शामिल हो गए प्रश्नों पर हर बार जब मैं Users तालिका में सम्मिलित करने के लिए (या अद्यतन) एक पंक्ति सभी CursorAdapter सुना रहा सूचित करने के लिए योजना क्या है?

दूसरे शब्दों में, अगर मैं जोड़ सकते हैं या तालिकाओं में से एक में एक नई पंक्ति को अद्यतन, मैं getContext().getContentResolver().notifyChange(itemUri, null) के साथ एक एकल सूचना भेजने के लिए चाहते हैं, ताकि किसी भी प्रश्न पर सभी CursorAdapter सुना रहा (USERS_TABLE, ARTICLES_USERS_JOIN_TABLE, COMMENTS_USERS_JOIN_TABLE) अपनी सामग्री को अपडेट करने के लिए एक अधिसूचना प्राप्त करें।

यदि यह संभव नहीं है, तो क्या सभी पर्यवेक्षकों को सूचित करने का कोई वैकल्पिक तरीका है?

उत्तर

5

आप विशेष उरी के साथ क्वेरी करने के लिए हो सकता है:

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

लेकिन मैं एक तरह से एक भी सूचना भेजने के लिए सोच भी नहीं सकते। ऐसा लगता है कि आपकी सबसे अच्छी पसंद प्रत्येक उरी के लिए अधिसूचना भेजना है जो तालिका को संशोधित करने के लिए संदर्भित करती है। इसलिए आपके सम्मिलित/अद्यतन/हटाए गए तरीके अधिसूचित कॉल करेंगे प्रभावित तालिका के आधार पर कई बार बदलें। "उपयोगकर्ताओं" में बदलावों के लिए यह 3 अधिसूचनाएं होगी - उपयोगकर्ता, लेखकों और टिप्पणियों - क्योंकि वे सभी "उपयोगकर्ता" तालिका पर निर्भर करते हैं।

1

prodaea द्वारा उत्तर दिया गया, यहां एक अन्य विकल्प है जिसे आप अधिसूचना उरी के लिए उपयोग कर सकते हैं। यह एक आदर्श समाधान नहीं है, लेकिन यह अधिसूचना के लिए केवल एक उरी का उपयोग करता है।

समाधान किसी भी तालिका नाम के बिना मुख्य उरी का उपयोग करना है (उदाहरण: सामग्री: //com.example.app.provider/) ARTICLES_USERS_JOIN_TABLE और COMMENTS_USERS_JOIN_TABLE के लिए क्वेरी विधि में अधिसूचना उरी के रूप में। इसलिए, जब भी किसी भी तालिका में परिवर्तन होता है तो संबंधित कर्सर अधिसूचित किया जाएगा। यद्यपि एक सीमा है। तालिका में परिवर्तन होने पर भी ARTICLES_USERS_JOIN_TABLE कर्सर अधिसूचित किया जाएगा।

टेबल के लिए, Users' and लेख ', आप अधिसूचना के लिए अपने विशिष्ट यूरिस का उपयोग कर सकते हैं।

+0

अधिसूचना कॉल करने से अधिक सुरुचिपूर्ण तरीका [satur9nine के उत्तर] में सुझाए गए अनुसार प्रत्येक सम्मिलन/अद्यतन/हटाएं के बाद बदलें (http://stackoverflow.com/a/11661855/5756760)! – Joni