Ikuti semua informasi yang diumumkan di Firebase Summit, dan pelajari bagaimana Firebase dapat membantu Anda mempercepat pengembangan aplikasi dan menjalankan aplikasi dengan percaya diri. Pelajari Lebih Lanjut

Bekerja dengan Daftar Data di Android

Dokumen ini mencakup bekerja dengan daftar data di Firebase. Untuk mempelajari dasar-dasar membaca dan menulis data Firebase, lihat Membaca dan Menulis Data di Android .

Dapatkan Referensi Basis Data

Untuk membaca dan menulis data dari database, Anda memerlukan instance dari DatabaseReference :

Kotlin+KTX

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

Java

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

Membaca dan menulis daftar

Tambahkan ke daftar data

Gunakan metode push() untuk menambahkan data ke daftar dalam aplikasi multipengguna. Metode push() menghasilkan kunci unik setiap kali anak baru ditambahkan ke referensi Firebase yang ditentukan. Dengan menggunakan kunci yang dihasilkan secara otomatis ini untuk setiap elemen baru dalam daftar, beberapa klien dapat menambahkan turunan ke lokasi yang sama pada waktu yang sama tanpa konflik penulisan. Kunci unik yang dihasilkan oleh push() didasarkan pada stempel waktu, sehingga item daftar secara otomatis diurutkan secara kronologis.

Anda dapat menggunakan referensi ke data baru yang dikembalikan oleh metode push() untuk mendapatkan nilai kunci anak yang dibuat secara otomatis atau set data untuk anak tersebut. Memanggil getKey() pada referensi push() mengembalikan nilai kunci yang dihasilkan secara otomatis.

Anda dapat menggunakan kunci yang dihasilkan secara otomatis ini untuk menyederhanakan perataan struktur data Anda. Untuk informasi selengkapnya, lihat contoh penyebaran data .

Dengarkan acara anak

Saat bekerja dengan daftar, aplikasi Anda harus mendengarkan peristiwa anak, bukan peristiwa nilai yang digunakan untuk objek tunggal.

Peristiwa anak dipicu sebagai respons terhadap operasi tertentu yang terjadi pada anak node dari operasi seperti anak baru yang ditambahkan melalui metode push() atau anak yang diperbarui melalui metode updateChildren() . Masing-masing bersama-sama dapat berguna untuk mendengarkan perubahan pada node tertentu dalam database.

Untuk mendengarkan acara anak di DatabaseReference , lampirkan ChildEventListener :

Pendengar Panggilan balik acara Penggunaan tipikal
ChildEventListener onChildAdded() Ambil daftar item atau dengarkan penambahan ke daftar item. Callback ini dipicu satu kali untuk setiap anak yang ada dan sekali lagi setiap kali anak baru ditambahkan ke jalur yang ditentukan. DataSnapshot diteruskan ke pendengar berisi data anak baru.
onChildChanged() Dengarkan perubahan pada item dalam daftar. Peristiwa ini dipicu setiap kali simpul anak dimodifikasi, termasuk modifikasi apa pun pada keturunan simpul anak. DataSnapshot diteruskan ke pendengar acara berisi data yang diperbarui untuk anak.
onChildRemoved() Dengarkan item yang dihapus dari daftar. DataSnapshot diteruskan ke event callback berisi data untuk anak yang dihapus.
onChildMoved() Dengarkan perubahan pada urutan item dalam daftar yang diurutkan. Kejadian ini dipicu setiap kali callback onChildChanged() dipicu oleh pembaruan yang menyebabkan penyusunan ulang anak. Ini digunakan dengan data yang dipesan dengan orderByChild atau orderByValue .

Misalnya, aplikasi blogging sosial mungkin menggunakan metode ini bersama-sama untuk memantau aktivitas di komentar postingan, seperti yang ditunjukkan di bawah ini:

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)

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);

Dengarkan peristiwa nilai

Saat menggunakan ChildEventListener adalah cara yang disarankan untuk membaca daftar data, ada situasi di mana melampirkan ValueEventListener ke referensi daftar berguna.

Melampirkan ValueEventListener ke daftar data akan mengembalikan seluruh daftar data sebagai DataSnapshot tunggal, yang kemudian dapat Anda ulangi untuk mengakses masing-masing turunan.

Meskipun hanya ada satu kecocokan untuk kueri, snapshot tetap berupa daftar; itu hanya berisi satu item. Untuk mengakses item, Anda perlu mengulangi hasilnya:

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())
        // ...
    }
})

Java

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

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

Pola ini dapat berguna saat Anda ingin mengambil semua turunan dari daftar dalam satu operasi, daripada mendengarkan peristiwa onChildAdded tambahan.

Pisahkan pendengar

Callback dihapus dengan memanggil metode removeEventListener() pada referensi database Firebase Anda.

Jika pendengar telah ditambahkan beberapa kali ke lokasi data, maka akan dipanggil beberapa kali untuk setiap kejadian, dan Anda harus melepaskannya dengan jumlah yang sama untuk menghapusnya sepenuhnya.

Memanggil removeEventListener() pada pendengar induk tidak secara otomatis menghapus pendengar yang terdaftar pada node anaknya; removeEventListener() juga harus dipanggil pada setiap anak pendengar untuk menghapus callback.

Menyortir dan memfilter data

Anda dapat menggunakan kelas Realtime Database Query untuk mengambil data yang diurutkan berdasarkan kunci, nilai, atau nilai turunan. Anda juga dapat memfilter hasil yang diurutkan ke sejumlah hasil tertentu atau rentang kunci atau nilai.

Sortir data

Untuk mengambil data yang diurutkan, mulailah dengan menentukan salah satu metode urutkan demi untuk menentukan bagaimana hasil diurutkan:

metode Penggunaan
orderByChild() Urutkan hasil berdasarkan nilai kunci anak tertentu atau jalur anak bersarang.
orderByKey() Urutan hasil dengan kunci anak.
orderByValue() Urutkan hasil berdasarkan nilai anak.

Anda hanya dapat menggunakan satu metode order-by pada satu waktu. Memanggil metode order-by beberapa kali dalam kueri yang sama akan menimbulkan kesalahan.

Contoh berikut menunjukkan bagaimana Anda dapat mengambil daftar postingan teratas pengguna yang diurutkan berdasarkan jumlah bintangnya:

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
    // ...
})

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
    // ...
});

Ini mendefinisikan kueri yang bila digabungkan dengan pendengar anak menyinkronkan klien dengan kiriman pengguna dari jalur di database berdasarkan ID pengguna mereka, diurutkan berdasarkan jumlah bintang yang diterima setiap kiriman. Teknik menggunakan ID sebagai kunci indeks ini disebut data fan out, Anda dapat membacanya lebih lanjut di Structure Your Database .

Panggilan ke metode orderByChild() menentukan kunci anak untuk mengurutkan hasil. Dalam hal ini, postingan diurutkan berdasarkan nilai anak "starCount" masing-masing. Kueri juga dapat diurutkan berdasarkan turunan bersarang, jika Anda memiliki data yang terlihat seperti ini:

"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",
  }
},

Dalam contoh ini, kita dapat mengurutkan elemen daftar berdasarkan nilai yang bersarang di bawah kunci metrics dengan menentukan jalur relatif ke anak bersarang dalam panggilan orderByChild() kita.

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
    // ...
})

Java

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

Untuk informasi selengkapnya tentang cara pengurutan tipe data lainnya, lihat Cara pengurutan data kueri .

Menyaring data

Untuk memfilter data, Anda bisa mengombinasikan salah satu metode batas atau rentang dengan metode urutkan saat membuat kueri.

metode Penggunaan
limitToFirst() Menetapkan jumlah item maksimum yang akan dikembalikan dari awal daftar hasil yang diurutkan.
limitToLast() Menetapkan jumlah item maksimum yang akan dikembalikan dari akhir daftar hasil yang diurutkan.
startAt() Mengembalikan item yang lebih besar atau sama dengan kunci atau nilai yang ditentukan bergantung pada metode urutkan menurut yang dipilih.
startAfter() Mengembalikan item yang lebih besar dari kunci atau nilai yang ditentukan bergantung pada metode urutkan menurut yang dipilih.
endAt() Mengembalikan item yang kurang dari atau sama dengan kunci atau nilai yang ditentukan bergantung pada metode urutkan menurut yang dipilih.
endBefore() Mengembalikan item kurang dari kunci atau nilai yang ditentukan bergantung pada metode urutkan menurut yang dipilih.
equalTo() Mengembalikan item yang sama dengan kunci atau nilai yang ditentukan bergantung pada metode urutkan berdasarkan yang dipilih.

Berbeda dengan metode order-by, Anda dapat menggabungkan beberapa fungsi limit atau range. Misalnya, Anda dapat menggabungkan metode startAt() dan endAt() untuk membatasi hasil ke rentang nilai tertentu.

Meskipun hanya ada satu kecocokan untuk kueri, snapshot tetap berupa daftar; itu hanya berisi satu item. Untuk mengakses item, Anda perlu mengulangi hasilnya:

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())
        // ...
    }
})

Java

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

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

Batasi jumlah hasil

Anda dapat menggunakan metode limitToFirst() dan limitToLast() untuk menyetel jumlah maksimum turunan yang akan disinkronkan untuk callback tertentu. Misalnya, jika Anda menggunakan limitToFirst() untuk menetapkan batas 100, awalnya Anda hanya menerima hingga 100 callback onChildAdded() . Jika Anda memiliki kurang dari 100 item yang disimpan di database Firebase, callback onChildAdded() akan diaktifkan untuk setiap item.

Saat item berubah, Anda menerima callback onChildAdded() untuk item yang masuk ke kueri dan callback onChildRemoved() untuk item yang keluar sehingga jumlah totalnya tetap 100.

Contoh berikut menunjukkan bagaimana contoh aplikasi blogging menentukan kueri untuk mengambil daftar 100 postingan terbaru oleh semua pengguna:

Kotlin+KTX

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

Java

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

Contoh ini hanya mendefinisikan kueri, untuk benar-benar menyinkronkan data, diperlukan pendengar terlampir.

Filter berdasarkan kunci atau nilai

Anda dapat menggunakan startAt() , startAfter() , endAt() , endBefore() , dan equalTo() untuk memilih titik awal, akhir, dan titik ekuivalensi arbitrer untuk kueri. Ini dapat berguna untuk membuat nomor halaman data atau menemukan item dengan turunan yang memiliki nilai tertentu.

Bagaimana data kueri diurutkan

Bagian ini menjelaskan cara data diurutkan menurut masing-masing metode urutkan menurut di kelas Query .

orderByChild

Saat menggunakan orderByChild() , data yang berisi kunci anak tertentu diurutkan sebagai berikut:

  1. Anak-anak dengan nilai null untuk kunci anak yang ditentukan didahulukan.
  2. Anak-anak dengan nilai false untuk kunci anak yang ditentukan muncul berikutnya. Jika beberapa anak memiliki nilai false , mereka diurutkan secara leksikografis berdasarkan kunci.
  3. Anak-anak dengan nilai true untuk kunci anak yang ditentukan muncul berikutnya. Jika beberapa anak memiliki nilai true , mereka diurutkan secara leksikografis berdasarkan kunci.
  4. Anak-anak dengan nilai numerik datang berikutnya, diurutkan dalam urutan menaik. Jika beberapa anak memiliki nilai numerik yang sama untuk simpul anak yang ditentukan, mereka akan diurutkan berdasarkan kunci.
  5. String muncul setelah angka dan diurutkan secara leksikografis dalam urutan menaik. Jika beberapa turunan memiliki nilai yang sama untuk simpul turunan tertentu, mereka diurutkan secara leksikografis berdasarkan kunci.
  6. Objek datang terakhir dan diurutkan secara leksikografis dengan kunci dalam urutan menaik.

orderByKey

Saat menggunakan orderByKey() untuk mengurutkan data Anda, data dikembalikan dalam urutan menaik berdasarkan kunci.

  1. Anak-anak dengan kunci yang dapat diurai sebagai bilangan bulat 32-bit didahulukan, diurutkan dalam urutan menaik.
  2. Anak-anak dengan nilai string sebagai kuncinya muncul berikutnya, diurutkan secara leksikografis dalam urutan menaik.

orderByValue

Saat menggunakan orderByValue() , turunan diurutkan berdasarkan nilainya. Kriteria pengurutannya sama seperti di orderByChild() , kecuali nilai node digunakan sebagai ganti nilai kunci anak yang ditentukan.

Langkah selanjutnya

,

Dokumen ini mencakup bekerja dengan daftar data di Firebase. Untuk mempelajari dasar-dasar membaca dan menulis data Firebase, lihat Membaca dan Menulis Data di Android .

Dapatkan Referensi Basis Data

Untuk membaca dan menulis data dari database, Anda memerlukan instance dari DatabaseReference :

Kotlin+KTX

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

Java

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

Membaca dan menulis daftar

Tambahkan ke daftar data

Gunakan metode push() untuk menambahkan data ke daftar dalam aplikasi multipengguna. Metode push() menghasilkan kunci unik setiap kali anak baru ditambahkan ke referensi Firebase yang ditentukan. Dengan menggunakan kunci yang dihasilkan secara otomatis ini untuk setiap elemen baru dalam daftar, beberapa klien dapat menambahkan turunan ke lokasi yang sama pada waktu yang sama tanpa konflik penulisan. Kunci unik yang dihasilkan oleh push() didasarkan pada stempel waktu, sehingga item daftar secara otomatis diurutkan secara kronologis.

Anda dapat menggunakan referensi ke data baru yang dikembalikan oleh metode push() untuk mendapatkan nilai kunci anak yang dibuat secara otomatis atau set data untuk anak tersebut. Memanggil getKey() pada referensi push() mengembalikan nilai kunci yang dihasilkan secara otomatis.

Anda dapat menggunakan kunci yang dihasilkan secara otomatis ini untuk menyederhanakan perataan struktur data Anda. Untuk informasi selengkapnya, lihat contoh penyebaran data .

Dengarkan acara anak

Saat bekerja dengan daftar, aplikasi Anda harus mendengarkan peristiwa anak, bukan peristiwa nilai yang digunakan untuk objek tunggal.

Peristiwa anak dipicu sebagai respons terhadap operasi tertentu yang terjadi pada anak node dari operasi seperti anak baru yang ditambahkan melalui metode push() atau anak yang diperbarui melalui metode updateChildren() . Masing-masing bersama-sama dapat berguna untuk mendengarkan perubahan pada node tertentu dalam database.

Untuk mendengarkan acara anak di DatabaseReference , lampirkan ChildEventListener :

Pendengar Panggilan balik acara Penggunaan tipikal
ChildEventListener onChildAdded() Ambil daftar item atau dengarkan penambahan ke daftar item. Callback ini dipicu satu kali untuk setiap anak yang ada dan sekali lagi setiap kali anak baru ditambahkan ke jalur yang ditentukan. DataSnapshot diteruskan ke pendengar berisi data anak baru.
onChildChanged() Dengarkan perubahan pada item dalam daftar. Peristiwa ini dipicu setiap kali simpul anak dimodifikasi, termasuk modifikasi apa pun pada keturunan simpul anak. DataSnapshot diteruskan ke pendengar acara berisi data yang diperbarui untuk anak.
onChildRemoved() Dengarkan item yang dihapus dari daftar. DataSnapshot diteruskan ke event callback berisi data untuk anak yang dihapus.
onChildMoved() Dengarkan perubahan pada urutan item dalam daftar yang diurutkan. Kejadian ini dipicu setiap kali callback onChildChanged() dipicu oleh pembaruan yang menyebabkan penyusunan ulang anak. Ini digunakan dengan data yang dipesan dengan orderByChild atau orderByValue .

Misalnya, aplikasi blogging sosial mungkin menggunakan metode ini bersama-sama untuk memantau aktivitas di komentar postingan, seperti yang ditunjukkan di bawah ini:

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)

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);

Dengarkan peristiwa nilai

Saat menggunakan ChildEventListener adalah cara yang disarankan untuk membaca daftar data, ada situasi di mana melampirkan ValueEventListener ke referensi daftar berguna.

Melampirkan ValueEventListener ke daftar data akan mengembalikan seluruh daftar data sebagai DataSnapshot tunggal, yang kemudian dapat Anda ulangi untuk mengakses masing-masing turunan.

Meskipun hanya ada satu kecocokan untuk kueri, snapshot tetap berupa daftar; itu hanya berisi satu item. Untuk mengakses item, Anda perlu mengulangi hasilnya:

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())
        // ...
    }
})

Java

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

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

Pola ini dapat berguna saat Anda ingin mengambil semua turunan dari daftar dalam satu operasi, daripada mendengarkan peristiwa onChildAdded tambahan.

Pisahkan pendengar

Callback dihapus dengan memanggil metode removeEventListener() pada referensi database Firebase Anda.

Jika pendengar telah ditambahkan beberapa kali ke lokasi data, maka akan dipanggil beberapa kali untuk setiap kejadian, dan Anda harus melepaskannya dengan jumlah yang sama untuk menghapusnya sepenuhnya.

Memanggil removeEventListener() pada pendengar induk tidak secara otomatis menghapus pendengar yang terdaftar pada node anaknya; removeEventListener() juga harus dipanggil pada setiap anak pendengar untuk menghapus callback.

Menyortir dan memfilter data

Anda dapat menggunakan kelas Realtime Database Query untuk mengambil data yang diurutkan berdasarkan kunci, nilai, atau nilai turunan. Anda juga dapat memfilter hasil yang diurutkan ke sejumlah hasil tertentu atau rentang kunci atau nilai.

Sortir data

Untuk mengambil data yang diurutkan, mulailah dengan menentukan salah satu metode urutkan demi untuk menentukan bagaimana hasil diurutkan:

metode Penggunaan
orderByChild() Urutkan hasil berdasarkan nilai kunci anak tertentu atau jalur anak bersarang.
orderByKey() Urutan hasil dengan kunci anak.
orderByValue() Urutkan hasil berdasarkan nilai anak.

Anda hanya dapat menggunakan satu metode order-by pada satu waktu. Memanggil metode order-by beberapa kali dalam kueri yang sama akan menimbulkan kesalahan.

Contoh berikut menunjukkan bagaimana Anda dapat mengambil daftar postingan teratas pengguna yang diurutkan berdasarkan jumlah bintangnya:

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
    // ...
})

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
    // ...
});

Ini mendefinisikan kueri yang bila digabungkan dengan pendengar anak menyinkronkan klien dengan kiriman pengguna dari jalur di database berdasarkan ID pengguna mereka, diurutkan berdasarkan jumlah bintang yang diterima setiap kiriman. Teknik menggunakan ID sebagai kunci indeks ini disebut data fan out, Anda dapat membacanya lebih lanjut di Structure Your Database .

Panggilan ke metode orderByChild() menentukan kunci anak untuk mengurutkan hasil. Dalam hal ini, postingan diurutkan berdasarkan nilai anak "starCount" masing-masing. Kueri juga dapat diurutkan berdasarkan turunan bersarang, jika Anda memiliki data yang terlihat seperti ini:

"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",
  }
},

Dalam contoh ini, kita dapat mengurutkan elemen daftar berdasarkan nilai yang bersarang di bawah kunci metrics dengan menentukan jalur relatif ke anak bersarang dalam panggilan orderByChild() kita.

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
    // ...
})

Java

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

Untuk informasi selengkapnya tentang cara pengurutan tipe data lainnya, lihat Cara pengurutan data kueri .

Menyaring data

Untuk memfilter data, Anda bisa mengombinasikan salah satu metode batas atau rentang dengan metode urutkan saat membuat kueri.

metode Penggunaan
limitToFirst() Menetapkan jumlah item maksimum yang akan dikembalikan dari awal daftar hasil yang diurutkan.
limitToLast() Menetapkan jumlah item maksimum yang akan dikembalikan dari akhir daftar hasil yang diurutkan.
startAt() Mengembalikan item yang lebih besar atau sama dengan kunci atau nilai yang ditentukan bergantung pada metode urutkan menurut yang dipilih.
startAfter() Mengembalikan item yang lebih besar dari kunci atau nilai yang ditentukan bergantung pada metode urutkan menurut yang dipilih.
endAt() Mengembalikan item yang kurang dari atau sama dengan kunci atau nilai yang ditentukan bergantung pada metode urutkan menurut yang dipilih.
endBefore() Mengembalikan item kurang dari kunci atau nilai yang ditentukan bergantung pada metode urutkan menurut yang dipilih.
equalTo() Mengembalikan item yang sama dengan kunci atau nilai yang ditentukan bergantung pada metode urutkan berdasarkan yang dipilih.

Berbeda dengan metode order-by, Anda dapat menggabungkan beberapa fungsi limit atau range. Misalnya, Anda dapat menggabungkan metode startAt() dan endAt() untuk membatasi hasil ke rentang nilai tertentu.

Meskipun hanya ada satu kecocokan untuk kueri, snapshot tetap berupa daftar; itu hanya berisi satu item. Untuk mengakses item, Anda perlu mengulangi hasilnya:

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())
        // ...
    }
})

Java

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

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

Batasi jumlah hasil

Anda dapat menggunakan metode limitToFirst() dan limitToLast() untuk menyetel jumlah maksimum turunan yang akan disinkronkan untuk callback tertentu. Misalnya, jika Anda menggunakan limitToFirst() untuk menetapkan batas 100, awalnya Anda hanya menerima hingga 100 callback onChildAdded() . Jika Anda memiliki kurang dari 100 item yang disimpan di database Firebase, callback onChildAdded() akan diaktifkan untuk setiap item.

Saat item berubah, Anda menerima callback onChildAdded() untuk item yang masuk ke kueri dan callback onChildRemoved() untuk item yang keluar sehingga jumlah totalnya tetap 100.

Contoh berikut menunjukkan bagaimana contoh aplikasi blogging menentukan kueri untuk mengambil daftar 100 postingan terbaru oleh semua pengguna:

Kotlin+KTX

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

Java

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

Contoh ini hanya mendefinisikan kueri, untuk benar-benar menyinkronkan data, diperlukan pendengar terlampir.

Filter berdasarkan kunci atau nilai

Anda dapat menggunakan startAt() , startAfter() , endAt() , endBefore() , dan equalTo() untuk memilih titik awal, akhir, dan titik ekuivalensi arbitrer untuk kueri. Ini dapat berguna untuk membuat nomor halaman data atau menemukan item dengan turunan yang memiliki nilai tertentu.

Bagaimana data kueri diurutkan

Bagian ini menjelaskan cara data diurutkan menurut masing-masing metode urutkan menurut di kelas Query .

orderByChild

Saat menggunakan orderByChild() , data yang berisi kunci anak tertentu diurutkan sebagai berikut:

  1. Anak-anak dengan nilai null untuk kunci anak yang ditentukan didahulukan.
  2. Anak-anak dengan nilai false untuk kunci anak yang ditentukan muncul berikutnya. Jika beberapa anak memiliki nilai false , mereka diurutkan secara leksikografis berdasarkan kunci.
  3. Anak-anak dengan nilai true untuk kunci anak yang ditentukan muncul berikutnya. Jika beberapa anak memiliki nilai true , mereka diurutkan secara leksikografis berdasarkan kunci.
  4. Anak-anak dengan nilai numerik datang berikutnya, diurutkan dalam urutan menaik. Jika beberapa anak memiliki nilai numerik yang sama untuk simpul anak yang ditentukan, mereka akan diurutkan berdasarkan kunci.
  5. String muncul setelah angka dan diurutkan secara leksikografis dalam urutan menaik. Jika beberapa turunan memiliki nilai yang sama untuk simpul turunan tertentu, mereka diurutkan secara leksikografis berdasarkan kunci.
  6. Objek datang terakhir dan diurutkan secara leksikografis dengan kunci dalam urutan menaik.

orderByKey

Saat menggunakan orderByKey() untuk mengurutkan data Anda, data dikembalikan dalam urutan menaik berdasarkan kunci.

  1. Anak-anak dengan kunci yang dapat diurai sebagai bilangan bulat 32-bit didahulukan, diurutkan dalam urutan menaik.
  2. Anak-anak dengan nilai string sebagai kuncinya muncul berikutnya, diurutkan secara leksikografis dalam urutan menaik.

orderByValue

Saat menggunakan orderByValue() , turunan diurutkan berdasarkan nilainya. Kriteria pengurutannya sama seperti di orderByChild() , kecuali nilai node digunakan sebagai ganti nilai kunci anak yang ditentukan.

Langkah selanjutnya