2012-12-30 12 views
20

1: n ilişkisi olan iki tablo yaşıyorum, içerik sağlayıcısı ve cursorloader kullanıyorum.yapıcı onu desteklemediğinde CursorLoader'da birleştirme sorgusu nasıl kullanılır

İmleç yükleyici ile çalışmak için bir katılma sorgusu nasıl yapılır? İçerik sağlayıcısı içinde rawSql ile bir şekilde hack olabilirim ama imleç yükleyici yapıcıda nasıl yapılacağını bana göre.

Çok teşekkürler! birleştirme için sorgular nasıl

CursorLoader (Bağlam kapsamı, URI, String [] çıkıntı String seçimi, String [] selectionArgs String sıralama)

Uri olabilir bir tablo

cevap

31
için tek nokta

Uri, herhangi bir tabloya işaret etmiyor. İşaret etmek istediğinizi gösterir.

İki tablonun Customer ve Order olduğunu varsayalım. Bir müşterinin çok fazla siparişi olabilir. Tüm bekleyen siparişleri almak için bir sorgu yürütmek istersiniz ... ancak müşterinin adı gibi ihtiyaç duyacağınız müşteri ile ilgili sütunlara katılmak istersiniz.

Ayrıca, bu tabloları yalnızca sorgulamak için zaten content://your.authority.goes.here/customer ve content://your.authority.goes.here/order tanımladığınızı varsayalım. senin /orderUri üzerinde

  1. müşterinin ekran adının katılmak ekleyin:

    İki seçeneğin var. Kullanılabilir başka bir sütuna sahip olmak, muhtemelen sağlayıcının mevcut tüketicilerini kırmayacaktır (test her zaman iyi bir fikir olsa da). Bu, ContactsContract'un yaptığı şeydir - tüm tabloların hemen hemen tüm sorgularında kişinin adı gibi bazı temel sütunlara katılır.

  2. , /order ile aynı temel sorgunun aynısını yapar, ancak birleşiminizi içerir. Bu durumda Uri olarak /orderWithCust kullanarak /orderWithCust kullanarak verileri değiştirmemelisiniz gerektiğini hatırlatmak için, update() ve delete() bir tür RuntimeException atabilirsiniz. Bir ContentProviderUri sistemini tasarlarken Sonunda

, REST Web hizmetinin URL sistemini tasarlarken benzer. Her iki durumda da, katılımcının sağlayıcı/sunucu tarafında yapılması gerekir ve bu nedenle bazı yararlı katılımları sunmak için tek tablodan bire-URL temelini kırmanız gerekebilir.

+1

Yukarıda ama katılmak kullanmanın benim durumda bütün noktasında cevabınızı okursanız ContentResolver bildirmek setNotificationUri() diyoruz sütunları almak için Sadece bir sorgu ile birden fazla ilgili tablodan. imleç yükleyiciden aldığım tek bir imlecin içinde, ContactContract.RawContact tablosundan ContactsContract.RawContact tablosundan ve ContactContract.DATA tablosundan DATA1'den ContactsContract.Contact tablosundan DISPLAY_NAME_PRIMARY öğesine ihtiyacım var.Şimdi Uri verirsem, tek Uri'nin bana nasıl yardımcı olabileceğini anlamıyorum ContactsContract.RawContact tablosuna işaret eden o zaman ContactsContract'un ilgili sütunlarına nasıl erişeceğim.İletişim ve ContactsContract.Data tablosu –

+1

@AbhishekChauhan: Sizin durumunuzda, 'ContentProvider' yazmadınız demektir, yani "hacklemezsiniz" demektir Sorunuzda iddia ettiğiniz gibi, içerik sağlayıcı içinde rawSql ile bir şekilde ". Cevabım, 'ContentProvider' yazan bir kişiye yöneliktir ve bu yüzden içeride birleştirme yapabilir. Durumunuzda, verilerinizi birden çok "İmleç" nesnesinden elle "birleştirmeniz" gerekecektir ve "Yükleyici" çerçevesi bu alanda çok fazla yardımcı olmayacaktır. Manşondan, bir 'AsyncTask' kullanıyorum, sonra' ContentResolver' kullanarak sorgulama yapabilir ve verilerinizi doInBackground() 'da birleştiririm sanırım. – CommonsWare

+0

ya ... Teşekkürler asynctask için kullanacağım ve daha sonra birleştireceğim ... bu bana daha iyi uyar –

4

ContentProvider alt sınıflarını kullanarak bir çözüm buldum. Diyelim ki tablo tblA'nız ve başka bir tblB tablonuz var. İki sınıf "AContentProvider" ve "BContentProvider" oluşturmanızı öneriyorum. En önemlisi, her iki tablonun aynı veritabanında kurulduğundan emin olun.

çözümün ana parçası da CursorLoader gelen arayacak ContentProvider içinde ContentProvider.query() geçersiz kılmak için - URI bunun hangisi karar verir:

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

Eğer görebileceğiniz gibi JOIN setTables() içinde yapılır.projeksiyon kullanarak Eğer sadece gerçekten ihtiyaç sütunları görüntülemek emin olun ve en önemlisi, hiçbir yinelenen sütun var, iki tablodan "id" gibi: geçersiz kılma

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

iyi kullanın ve deneyin alt sınıflarda yapabileceğiniz kadar iş yapın; örneğin: benim geçersiz kılınmış sorgusu() yöntemleri imleç sonuç kümesi değişikliklerin .:

c.setNotificationUri(getContext().getContentResolver(), uri); 
İlgili konular