2012-12-30 10 views
20

मेरे पास 1: n रिलेशनशिप के साथ दो टेबल हैं, मैं सामग्री प्रदाता और कर्सरलोडर का उपयोग कर रहा हूं।कर्सर लोडर में जॉइन क्वेरी का उपयोग कैसे करें जब उसका कन्स्ट्रक्टर इसका समर्थन नहीं करता है

कर्सर लोडर के साथ काम करने के लिए मैं जॉइन क्वेरी कैसे करूं? मैं सामग्री प्रदाता के अंदर कच्चे एसक्यूएल के साथ इसे किसी भी तरह से हैक कर सकता हूं लेकिन कर्सर लोडर कन्स्ट्रक्टर में इसे कैसे करना है मेरे बाहर है।

बहुत बहुत धन्यवाद!

CursorLoader (संदर्भ संदर्भ, उरी uri, String [] प्रक्षेपण, स्ट्रिंग चयन, String [] selectionArgs, स्ट्रिंग sortOrder)

कैसे शामिल हो के लिए क्वेरी करेगा जब उरी सकता है केवल एक ही मेज

उत्तर

31
इंगित

Uri किसी भी तालिका को इंगित नहीं करता है। यह जो कुछ भी आपको लगता है उसे इंगित करता है।

आइए दिखाएं कि आपकी दो टेबल Customer और Order हैं। एक ग्राहक के पास कई ऑर्डर हो सकते हैं। आप सभी बकाया ऑर्डर प्राप्त करने के लिए एक क्वेरी निष्पादित करना चाहते हैं ... लेकिन आप कुछ ग्राहक-संबंधित कॉलम में शामिल होना चाहते हैं, जिनकी आपको आवश्यकता होगी, जैसे कि ग्राहक का नाम।

आइए आगे बताएं कि आपके पास पहले से ही content://your.authority.goes.here/customer और content://your.authority.goes.here/order है जो उन तालिकाओं को पूरी तरह से क्वेरी करने के लिए परिभाषित किया गया है। अपने /orderUri पर

  1. ग्राहक के प्रदर्शन नाम के शामिल होने करें:

    आपके पास दो विकल्प। एक और उपलब्ध कॉलम होने से शायद प्रदाता के मौजूदा उपभोक्ताओं को तोड़ नहीं होगा (हालांकि परीक्षण हमेशा एक अच्छा विचार है)। यह ContactsContract करता है - यह सभी बेस कॉलम में संपर्क करता है, जैसे संपर्क के नाम की तरह, सभी तालिकाओं के बहुत सारे प्रश्नों पर।

  2. content://your.authority.goes.here/orderWithCust बनाएं जो /order के समान मूल क्वेरी करता है, लेकिन इसमें शामिल है। इस मामले में, आपके पास insert(), update(), और delete() कुछ प्रकार के RuntimeException फेंक सकते हैं, आपको याद दिलाने के लिए कि आपको /orderWithCust का उपयोग Uri के रूप में डेटा संशोधित नहीं करना चाहिए।

अंत में, एक ContentProviderUri प्रणाली को डिजाइन करने के लिए एक बाकी वेब सेवा के URL प्रणाली को डिजाइन करने के समान है। दोनों मामलों में, प्रदाता/सर्वर पक्ष पर शामिल होना पड़ता है, और इसलिए आपको कुछ उपयोगी जुड़ने के लिए एक-टेबल-टू-वन-यूआरएल बेसलाइन तोड़ने की आवश्यकता हो सकती है।

+1

मैं ऊपर, लेकिन में शामिल होने का उपयोग करने का मेरे मामले पूरे मुद्दे में अपना जवाब पढ़ स्तंभों को पुन: प्राप्त करने के लिए है एकाधिक संबंधित तालिका से केवल एक प्रश्न के साथ। कर्सर लोडर से प्राप्त होने वाले एक कर्सर के अंदर मुझे संपर्कों से DISPLAY_NAME_PRIMARY की आवश्यकता है। संपर्क तालिका, संपर्क से ACCOUNT_NAME संपर्क करें। संपर्क से संपर्क करें और डेटा से संपर्क करें। डेटा तालिका.अब मुझे समझ में नहीं आता कि कैसे उरी इस से मेरी सहायता कर सकती है क्योंकि अगर मैं उरी देता हूं तो ContactsContract.RawContact मेज की ओर इशारा करते मैं कैसे ContactsContract.Contact और ContactsContract.Data तालिका –

+1

@AbhishekChauhan के संबंधी कॉलम का उपयोग करेंगे: ठीक है, आपके मामले में, आप 'ContentProvider', जिसका अर्थ है कि आप" यह नहीं हैक कर सकते हैं नहीं लिखा था किसी भी तरह सामग्री प्रदाता के अंदर rawSql के साथ ", जैसा कि आपने अपने प्रश्न में दावा किया था। मेरा उत्तर किसी ऐसे व्यक्ति के लिए है जो 'ContentProvider' लिख रहा है और इसलिए इसके अंदर शामिल हो सकता है। आपके मामले में, आपको अपने डेटा को मैन्युअल रूप से एकाधिक 'कर्सर' ऑब्जेक्ट्स से "जुड़ना" होगा, और 'लोडर' ढांचा इस क्षेत्र में ज्यादा मदद नहीं करेगा। कफ के बाहर, मैं 'AsyncTask' का उपयोग करता हूं, फिर' ContentResolver' का उपयोग करके क्वेरी करता हूं और 'डेटा में' डिनबैकग्राउंड() 'में अपना डेटा मर्ज करता हूं। – CommonsWare

+0

या ... धन्यवाद, मैं इसके लिए asynctask का उपयोग करूंगा और बाद में विलय करूँगा ... यह मुझे बेहतर तरीके से उपयुक्त करेगा –

4

मुझे ContentProvider के उप-वर्गों का उपयोग करके समाधान मिला। मान लें कि आपके पास टेबल tbla और एक और तालिका tblb है। मैं दो कक्षाओं "AcontentProvider" और "BContentProvider" बनाने की सलाह देते हैं। सबसे महत्वपूर्ण बात यह सुनिश्चित करें कि दोनों टेबल एक ही डेटाबेस में स्थापित हैं।

समाधान के मुख्य भाग ContentProvider है कि आप अपने CursorLoader से फोन करेगा में ContentProvider.query() ओवरराइड करने के लिए है - यूआरआई का फैसला करता है, जो एक यह है:

@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; 
} 

आप देख सकते हैं, जॉइन सेटटेबल्स में किया जाता है()प्रक्षेपण का उपयोग करना आप सुनिश्चित करें कि आप केवल कॉलम आप वास्तव में जरूरत है प्रदर्शित करने के लिए और सभी के अधिकांश, आप कोई डुप्लिकेट कॉलम है, दोनों तालिकाओं से "आईडी" की तरह: ओवरराइड की

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

उपयोग करें और करने की कोशिश उप-वर्गों में जितना संभव हो उतना काम करें; उदाहरण के लिए: मेरे सभी ओवरराइड क्वेरी() पद्धतियों setNotificationUri() फोन ContentResolver सूचित करने के लिए करता है, तो कर्सर परिणाम सेट परिवर्तन .:

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