Android'de Veri Listeleriyle Çalışın

Bu belge, Firebase'deki veri listeleriyle çalışmayı kapsar. Firebase verilerini okuma ve yazmanın temellerini öğrenmek için Android'de Veri Okuma ve Yazma bölümüne bakın.

Bir Veritabanı Referansı Alın

Veritabanından veri okumak ve yazmak için bir DatabaseReference örneğine ihtiyacınız vardır:

Java

private DatabaseReference mDatabase;
// ...
mDatabase = FirebaseDatabase.getInstance().getReference();

Kotlin+KTX

private lateinit var database: DatabaseReference
// ...
database = Firebase.database.reference

Listeleri okuma ve yazma

Veri listesine ekle

Çok kullanıcılı uygulamalarda bir listeye veri eklemek için push() yöntemini kullanın. push() yöntemi, belirtilen Firebase referansına her yeni bir alt öğe eklendiğinde benzersiz bir anahtar oluşturur. Listedeki her yeni öğe için bu otomatik oluşturulan anahtarları kullanarak, birkaç istemci, yazma çakışmaları olmadan aynı anda aynı konuma alt öğeler ekleyebilir. push() tarafından oluşturulan benzersiz anahtar bir zaman damgasını temel alır, bu nedenle liste öğeleri otomatik olarak kronolojik olarak sıralanır.

Çocuğun otomatik olarak oluşturulan anahtarının değerini almak veya alt öğe için veri ayarlamak için push() yöntemi tarafından döndürülen yeni verilere başvuruyu kullanabilirsiniz. Bir push() başvurusunda getKey() çağrılması, otomatik olarak oluşturulan anahtarın değerini döndürür.

Veri yapınızı düzleştirmeyi basitleştirmek için bu otomatik oluşturulan anahtarları kullanabilirsiniz. Daha fazla bilgi için, veri yayma örneğine bakın.

Çocuk olaylarını dinleyin

Listelerle çalışırken, uygulamanız tek nesneler için kullanılan değer olayları yerine alt olayları dinlemelidir.

Alt olaylar, push() yöntemi aracılığıyla eklenen yeni bir alt öğe veya updateChildren() yöntemi aracılığıyla güncellenen bir alt öğe gibi bir işlemden bir düğümün alt öğelerinin başına gelen belirli işlemlere yanıt olarak tetiklenir. Bunların her biri birlikte, bir veritabanındaki belirli bir düğümde yapılan değişiklikleri dinlemek için yararlı olabilir.

DatabaseReference alt olayları dinlemek için bir ChildEventListener ekleyin:

dinleyici Olay geri arama Tipik kullanım
ChildEventListener onChildAdded() Öğe listelerini alın veya bir öğe listesine eklemeleri dinleyin. Bu geri arama, mevcut her alt öğe için bir kez tetiklenir ve ardından belirtilen yola her yeni bir alt öğe eklendiğinde yeniden tetiklenir. Dinleyiciye iletilen DataSnapshot , yeni alt öğenin verilerini içerir.
onChildChanged() Listedeki öğelerdeki değişiklikleri dinleyin. Bu olay, alt düğümün alt öğelerinde yapılan değişiklikler de dahil olmak üzere, bir alt düğüm değiştirildiğinde tetiklenir. Olay dinleyicisine iletilen DataSnapshot , alt öğe için güncellenmiş verileri içerir.
onChildRemoved() Listeden kaldırılan öğeleri dinleyin. Olay geri çağrısına geçirilen DataSnapshot , kaldırılan alt öğenin verilerini içerir.
onChildMoved() Sıralı bir listedeki öğelerin sırasına ilişkin değişiklikleri dinleyin. Bu olay, onChildChanged() geri çağrısı, alt öğenin yeniden sıralanmasına neden olan bir güncelleme tarafından tetiklendiğinde tetiklenir. orderByChild veya orderByValue ile sipariş edilen verilerle kullanılır.

Örneğin, bir sosyal blog uygulaması, aşağıda gösterildiği gibi, bir gönderinin yorumlarındaki etkinliği izlemek için bu yöntemleri birlikte kullanabilir:

Java

ChildEventListener childEventListener = new ChildEventListener() {
    @Override
    public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
        Log.d(TAG, "onChildAdded:" + dataSnapshot.getKey());

        // A new comment has been added, add it to the displayed list
        Comment comment = dataSnapshot.getValue(Comment.class);

        // ...
    }

    @Override
    public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) {
        Log.d(TAG, "onChildChanged:" + dataSnapshot.getKey());

        // A comment has changed, use the key to determine if we are displaying this
        // comment and if so displayed the changed comment.
        Comment newComment = dataSnapshot.getValue(Comment.class);
        String commentKey = dataSnapshot.getKey();

        // ...
    }

    @Override
    public void onChildRemoved(DataSnapshot dataSnapshot) {
        Log.d(TAG, "onChildRemoved:" + dataSnapshot.getKey());

        // A comment has changed, use the key to determine if we are displaying this
        // comment and if so remove it.
        String commentKey = dataSnapshot.getKey();

        // ...
    }

    @Override
    public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {
        Log.d(TAG, "onChildMoved:" + dataSnapshot.getKey());

        // A comment has changed position, use the key to determine if we are
        // displaying this comment and if so move it.
        Comment movedComment = dataSnapshot.getValue(Comment.class);
        String commentKey = dataSnapshot.getKey();

        // ...
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        Log.w(TAG, "postComments:onCancelled", databaseError.toException());
        Toast.makeText(mContext, "Failed to load comments.",
                Toast.LENGTH_SHORT).show();
    }
};
databaseReference.addChildEventListener(childEventListener);

Kotlin+KTX

val childEventListener = object : ChildEventListener {
    override fun onChildAdded(dataSnapshot: DataSnapshot, previousChildName: String?) {
        Log.d(TAG, "onChildAdded:" + dataSnapshot.key!!)

        // A new comment has been added, add it to the displayed list
        val comment = dataSnapshot.getValue<Comment>()

        // ...
    }

    override fun onChildChanged(dataSnapshot: DataSnapshot, previousChildName: String?) {
        Log.d(TAG, "onChildChanged: ${dataSnapshot.key}")

        // A comment has changed, use the key to determine if we are displaying this
        // comment and if so displayed the changed comment.
        val newComment = dataSnapshot.getValue<Comment>()
        val commentKey = dataSnapshot.key

        // ...
    }

    override fun onChildRemoved(dataSnapshot: DataSnapshot) {
        Log.d(TAG, "onChildRemoved:" + dataSnapshot.key!!)

        // A comment has changed, use the key to determine if we are displaying this
        // comment and if so remove it.
        val commentKey = dataSnapshot.key

        // ...
    }

    override fun onChildMoved(dataSnapshot: DataSnapshot, previousChildName: String?) {
        Log.d(TAG, "onChildMoved:" + dataSnapshot.key!!)

        // A comment has changed position, use the key to determine if we are
        // displaying this comment and if so move it.
        val movedComment = dataSnapshot.getValue<Comment>()
        val commentKey = dataSnapshot.key

        // ...
    }

    override fun onCancelled(databaseError: DatabaseError) {
        Log.w(TAG, "postComments:onCancelled", databaseError.toException())
        Toast.makeText(context, "Failed to load comments.",
                Toast.LENGTH_SHORT).show()
    }
}
databaseReference.addChildEventListener(childEventListener)

Değer olaylarını dinleyin

Veri listelerini okumanın önerilen yolu ChildEventListener kullanmak olsa da, bir liste başvurusuna ValueEventListener yararlı olduğu durumlar vardır.

Bir veri listesine ValueEventListener eklemek, tüm veri listesini tek bir DataSnapshot olarak döndürür ve daha sonra tek tek alt öğelere erişmek için döngüye girebilirsiniz.

Sorgu için yalnızca tek bir eşleşme olsa bile, anlık görüntü yine bir listedir; sadece tek bir öğe içerir. Öğeye erişmek için sonucun üzerinden geçmeniz gerekir:

Java

// My top posts by number of stars
myTopPostsQuery.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
            // TODO: handle the post
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        // Getting Post failed, log a message
        Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
        // ...
    }
});

Kotlin+KTX

// My top posts by number of stars
myTopPostsQuery.addValueEventListener(object : ValueEventListener {
    override fun onDataChange(dataSnapshot: DataSnapshot) {
        for (postSnapshot in dataSnapshot.children) {
            // TODO: handle the post
        }
    }

    override fun onCancelled(databaseError: DatabaseError) {
        // Getting Post failed, log a message
        Log.w(TAG, "loadPost:onCancelled", databaseError.toException())
        // ...
    }
})

Bu model, ek onChildAdded olaylarını dinlemek yerine bir listenin tüm alt öğelerini tek bir işlemde almak istediğinizde yararlı olabilir.

Dinleyicileri ayır

Firebase veritabanı referansınızdaki removeEventListener() yöntemi çağrılarak geri aramalar kaldırılır.

Bir dinleyici bir veri konumuna birden çok kez eklendiyse, her olay için birden çok kez çağrılır ve onu tamamen kaldırmak için aynı sayıda ayırmanız gerekir.

Bir üst dinleyicide removeEventListener() öğesinin çağrılması, alt düğümlerinde kayıtlı dinleyicileri otomatik olarak kaldırmaz; removeEventListener() , geri aramayı kaldırmak için tüm alt dinleyicilerde de çağrılmalıdır.

Verileri sıralama ve filtreleme

Anahtara, değere veya bir alt öğenin değerine göre sıralanmış verileri almak için Realtime Database Query sınıfını kullanabilirsiniz. Ayrıca, sıralanan sonucu belirli sayıda sonuca veya bir dizi anahtar veya değere göre filtreleyebilirsiniz.

Verileri sırala

Sıralanmış verileri almak için, sonuçların nasıl sıralandığını belirlemek için sıralama yöntemlerinden birini belirterek başlayın:

Yöntem kullanım
orderByChild() Sonuçları belirtilen bir alt anahtarın veya iç içe geçmiş alt yolun değerine göre sıralayın.
orderByKey() Sonuçları alt anahtarlara göre sıralayın.
orderByValue() Sonuçları alt değerlere göre sıralayın.

Bir seferde yalnızca bir sipariş yöntemi kullanabilirsiniz. Aynı sorguda bir sipariş yönteminin birden çok kez çağrılması bir hata verir.

Aşağıdaki örnek, yıldız sayısına göre sıralanmış bir kullanıcının en iyi gönderilerinin bir listesini nasıl alabileceğinizi gösterir:

Java

// My top posts by number of stars
String myUserId = getUid();
Query myTopPostsQuery = databaseReference.child("user-posts").child(myUserId)
        .orderByChild("starCount");
myTopPostsQuery.addChildEventListener(new ChildEventListener() {
    // TODO: implement the ChildEventListener methods as documented above
    // ...
});

Kotlin+KTX

// My top posts by number of stars
val myUserId = uid
val myTopPostsQuery = databaseReference.child("user-posts").child(myUserId)
    .orderByChild("starCount")

myTopPostsQuery.addChildEventListener(object : ChildEventListener {
    // TODO: implement the ChildEventListener methods as documented above
    // ...
})

Bu, bir alt dinleyiciyle birleştirildiğinde, istemciyi, her gönderinin aldığı yıldız sayısına göre sıralanan, kullanıcı kimliğine göre veritabanındaki yoldan kullanıcının gönderileriyle senkronize eden bir sorgu tanımlar. ID'leri indeks anahtarları olarak kullanma tekniğine data fan out adı verilir, bununla ilgili daha fazla bilgiyi Veritabanınızı Yapın bölümünde okuyabilirsiniz.

orderByChild() yöntemine yapılan çağrı, sonuçların sıralanacağı alt anahtarı belirtir. Bu durumda, gönderiler ilgili "starCount" alt öğelerinin değerine göre sıralanır. Şuna benzeyen verileriniz olması durumunda, sorgular iç içe geçmiş çocuklar tarafından da sipariş edilebilir:

"posts": {
  "ts-functions": {
    "metrics": {
      "views" : 1200000,
      "likes" : 251000,
      "shares": 1200,
    },
    "title" : "Why you should use TypeScript for writing Cloud Functions",
    "author": "Doug",
  },
  "android-arch-3": {
    "metrics": {
      "views" : 900000,
      "likes" : 117000,
      "shares": 144,
    },
    "title" : "Using Android Architecture Components with Firebase Realtime Database (Part 3)",
    "author": "Doug",
  }
},

Bu örnekte, orderByChild() çağrımızda yuvalanmış alt öğenin göreli yolunu belirterek, metrics anahtarının altında yuvalanmış değerlere göre liste öğelerimizi sıralayabiliriz.

Java

// Most viewed posts
Query myMostViewedPostsQuery = databaseReference.child("posts")
        .orderByChild("metrics/views");
myMostViewedPostsQuery.addChildEventListener(new ChildEventListener() {
    // TODO: implement the ChildEventListener methods as documented above
    // ...
});

Kotlin+KTX

// Most viewed posts
val myMostViewedPostsQuery = databaseReference.child("posts")
        .orderByChild("metrics/views")
myMostViewedPostsQuery.addChildEventListener(object : ChildEventListener {
    // TODO: implement the ChildEventListener methods as documented above
    // ...
})

Diğer veri türlerinin nasıl sıralandığı hakkında daha fazla bilgi için bkz. Sorgu verileri nasıl sıralanır .

Verileri filtreleme

Verileri filtrelemek için, bir sorgu oluştururken sınır veya aralık yöntemlerinden herhangi birini sıralama yöntemiyle birleştirebilirsiniz.

Yöntem kullanım
limitToFirst() Sıralı sonuç listesinin başından döndürülecek maksimum öğe sayısını ayarlar.
limitToLast() Sıralı sonuç listesinin sonundan döndürülecek maksimum öğe sayısını ayarlar.
startAt() Seçilen sıralama yöntemine bağlı olarak belirtilen anahtara veya değere eşit veya daha büyük öğeleri döndürün.
startAfter() Seçilen sıralama yöntemine bağlı olarak belirtilen anahtar veya değerden daha büyük öğeleri döndürün.
endAt() Seçilen sıralama yöntemine bağlı olarak, belirtilen anahtara veya değere eşit veya daha küçük öğeleri döndürün.
endBefore() Seçilen sıralama yöntemine bağlı olarak belirtilen anahtar veya değerden daha az öğeleri döndürün.
equalTo() Seçilen sıralama yöntemine bağlı olarak belirtilen anahtara veya değere eşit öğeleri döndürün.

Sıralama yöntemlerinden farklı olarak, birden fazla limit veya aralık fonksiyonunu birleştirebilirsiniz. Örneğin, sonuçları belirli bir değer aralığıyla sınırlamak için startAt() ve endAt() yöntemlerini birleştirebilirsiniz.

Sorgu için yalnızca tek bir eşleşme olsa bile, anlık görüntü yine bir listedir; sadece tek bir öğe içerir. Öğeye erişmek için sonucun üzerinden geçmeniz gerekir:

Java

// My top posts by number of stars
myTopPostsQuery.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
            // TODO: handle the post
        }
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        // Getting Post failed, log a message
        Log.w(TAG, "loadPost:onCancelled", databaseError.toException());
        // ...
    }
});

Kotlin+KTX

// My top posts by number of stars
myTopPostsQuery.addValueEventListener(object : ValueEventListener {
    override fun onDataChange(dataSnapshot: DataSnapshot) {
        for (postSnapshot in dataSnapshot.children) {
            // TODO: handle the post
        }
    }

    override fun onCancelled(databaseError: DatabaseError) {
        // Getting Post failed, log a message
        Log.w(TAG, "loadPost:onCancelled", databaseError.toException())
        // ...
    }
})

Sonuç sayısını sınırlayın

Belirli bir geri arama için eşitlenecek maksimum çocuk sayısını ayarlamak için limitToFirst() ve limitToLast() yöntemlerini kullanabilirsiniz. Örneğin, 100'lük bir sınır belirlemek için limitToFirst() 'i kullanırsanız, başlangıçta yalnızca 100'e kadar onChildAdded() geri araması alırsınız. Firebase veritabanınızda depolanan 100'den az öğeniz varsa, her öğe için bir onChildAdded() geri çağrısı tetiklenir.

Öğeler değiştikçe, sorguya giren öğeler için onChildRemoved() geri çağrıları ve sorgudan çıkan öğeler için onChildAdded() geri çağrıları alırsınız, böylece toplam sayı 100'de kalır.

Aşağıdaki örnek, örnek blog uygulamasının tüm kullanıcılar tarafından en son 100 gönderiyi içeren bir listeyi almak için bir sorguyu nasıl tanımladığını gösterir:

Java

// Last 100 posts, these are automatically the 100 most recent
// due to sorting by push() keys
Query recentPostsQuery = databaseReference.child("posts")
        .limitToFirst(100);

Kotlin+KTX

// Last 100 posts, these are automatically the 100 most recent
// due to sorting by push() keys.
databaseReference.child("posts").limitToFirst(100)

Bu örnek yalnızca, bağlı bir dinleyiciye sahip olması gereken verileri gerçekten senkronize etmek için bir sorgu tanımlar.

Anahtar veya değere göre filtrele

Sorgular için isteğe bağlı başlangıç, bitiş ve denklik noktaları seçmek için startAt() , startAfter() , endAt() , endBefore() ve equalTo() kullanabilirsiniz. Bu, verileri sayfalamak veya belirli bir değere sahip alt öğeleri olan öğeleri bulmak için yararlı olabilir.

Sorgu verileri nasıl sıralanır?

Bu bölüm, verilerin Query sınıfındaki sıralama yöntemlerinin her birine göre nasıl sıralandığını açıklar.

orderByChild

orderByChild() kullanılırken, belirtilen alt anahtarı içeren veriler aşağıdaki gibi sıralanır:

  1. Belirtilen alt anahtar için null değeri olan çocuklar önce gelir.
  2. Ardından, belirtilen alt anahtar için false değerine sahip çocuklar gelir. Birden çok alt öğe false değerine sahipse, bunlar anahtara göre sözlükbilimsel olarak sıralanır.
  3. Ardından belirtilen alt anahtar için true değerine sahip çocuklar gelir. Birden çok alt öğe true değerine sahipse, bunlar anahtara göre sözlükbilimsel olarak sıralanır.
  4. Sayısal değeri olan çocuklar, artan düzende sıralanır. Birden çok alt öğe, belirtilen alt düğüm için aynı sayısal değere sahipse, bunlar anahtara göre sıralanır.
  5. Dizeler sayılardan sonra gelir ve sözlükbilimsel olarak artan düzende sıralanır. Birden çok alt öğe, belirtilen alt düğüm için aynı değere sahipse, anahtara göre sözlükbilimsel olarak sıralanır.
  6. Nesneler en sonda gelir ve artan düzende anahtara göre sözlükbilimsel olarak sıralanır.

orderByKey

Verilerinizi sıralamak için orderByKey() kullanıldığında, veriler anahtara göre artan sırada döndürülür.

  1. 32-bit tamsayı olarak ayrıştırılabilen bir anahtarı olan çocuklar, artan düzende sıralanarak önce gelir.
  2. Anahtar olarak dize değerine sahip çocuklar, sözlükbilimsel olarak artan düzende sıralanır.

orderByValue

orderByValue() kullanılırken, çocuklar değerlerine göre sıralanır. Sıralama ölçütü, belirtilen bir alt anahtarın değeri yerine düğümün değerinin kullanılması dışında orderByChild() ile aynıdır.

Sonraki adımlar