Android RecyclerView: Apa itu, Pelajari dengan Contoh Sederhana

โšก Ringkasan Cerdas

RecyclerView adalah aplikasi canggih. Android Widget yang menampilkan kumpulan data besar yang dapat digulir secara efisien dengan mendaur ulang sejumlah tampilan yang terbatas. Widget ini bergantung pada adaptor, pengelola tata letak, dan pemegang tampilan untuk mengikat koleksi data yang berubah saat runtime.

  • ๐Ÿ“ฑ Apa itu: RecyclerView adalah penerus yang fleksibel untuk ListView dan GridView untuk menampilkan koleksi data yang besar.
  • ๐Ÿงฑ Tampilan dan Grup Tampilan: Android Menggambar antarmuka menggunakan kelas View dan ViewGroup, dengan LayoutParams yang mengontrol ukuran dan posisi.
  • ๐Ÿ”„ Adapter: Pola adapter mengubah array data menjadi ViewHolder yang dapat diterima oleh RecyclerView.
  • ๐Ÿ“ Pengelola Tata Letak: Pengelola tata letak mengatur item secara linear atau dalam bentuk kisi dan memberi sinyal kapan tampilan dapat digunakan kembali.
  • โ™ป๏ธ Mendaur ulang: Tampilan di luar layar digunakan kembali alih-alih dibuat ulang, yang menghemat memori dan menjaga kelancaran pengguliran.
  • ๏ธ Membangun langkah-langkah: Tambahkan Gradle dependensi, membuat tata letak item, ViewHolder, adapter, dan LayoutManager.

Android Tampilan Pendaur Ulang

Apa yang dimaksud dengan RecyclerView Android?

The Tampilan Pendaur Ulang RecyclerView adalah versi GridView dan ListView yang lebih fleksibel dan canggih. Ini adalah wadah untuk menampilkan kumpulan data besar yang dapat digulir secara efisien dengan mempertahankan jumlah tampilan yang terbatas. Anda dapat menggunakan widget RecyclerView ketika Anda memiliki koleksi data yang elemen-elemennya berubah saat runtime tergantung pada peristiwa jaringan atau tindakan pengguna.

views

The Android Platform ini menggunakan kelas View dan ViewGroup untuk menggambar item di layar. Kelas-kelas ini bersifat absolut.tract dan diperluas ke implementasi yang berbeda untuk menyesuaikan kasus penggunaan. TextView, misalnya, memiliki tujuan sederhana untuk menampilkan konten teks di layar. EditText memperluas dari kelas View yang sama dan menambahkan lebih banyak fungsionalitas untuk memungkinkan pengguna memasukkan data.

Kita dapat membuat tampilan kustom sendiri untuk mencapai fleksibilitas yang lebih besar saat pengembangan.ping Antarmuka pengguna. Kelas View menyediakan metode yang dapat kita timpa untuk menggambar di layar dan cara untuk meneruskan parameter seperti lebar, tinggi, dan atribut khusus kita sendiri yang ingin kita tambahkan ke View agar berperilaku sesuai keinginan kita.

LihatGrup

Kelas ViewGroup adalah sejenis View, tetapi tidak seperti kelas View sederhana yang hanya bertugas menampilkan, ViewGroup memberi kita kemampuan untuk menggabungkan beberapa view ke dalam satu view, yang dapat kita referensikan secara keseluruhan. Dalam hal ini, View yang dibuat di tingkat atas yang kita tambahkan view sederhana lainnya disebut "parent," dan view yang ditambahkan di dalamnya disebut "children."

Kita dapat membayangkan View sebagai sebuah Array dan ViewGroup sebagai Array dari Array. Karena Array dari Array itu sendiri adalah sebuah Array, kita dapat melihat bagaimana ViewGroup dapat diperlakukan seperti sebuah View.

var arr1 = [1,2,3] //imagine a simple View as an Array
//we can imagine this as a NumberTextView which doesn't really exist
//but we could imagine there's one that makes it easy to use numbers
var arr2 = ["a","b","c"] // We can imagine this as another simple view

var nestedArr = [arr1,arr2] //in our analogy, we can now group views
//together and the structure that would hold that would be what we call the ViewGroup

ViewGroup juga memungkinkan kita untuk menentukan bagaimana elemen anak diatur di dalam tampilan, misalnya, apakah tata letaknya vertikal atau horizontal. Kita dapat memiliki aturan interaksi yang berbeda di dalam View. Misalnya, TextView yang berurutan harus memiliki jarak 12dp, sedangkan ImageView yang diikuti oleh TextView harus memiliki jarak 5dp.

Hal ini akan terjadi jika kita sedang mengembangkanping Membuat ViewGroup sendiri dari awal. Untuk mempermudah konfigurasi ini, Android menyediakan kelas bernama LayoutParams, yang dapat kita gunakan untuk memasukkan konfigurasi ini.

The Android dokumentasi menyediakan beberapa parameter default yang akan kita terapkan saat mengkonfigurasi ViewGroup kita sendiri. Beberapa parameter umum berkaitan dengan lebar, tinggi, dan margin. Secara default, konfigurasi ini memiliki struktur android:layout_height untuk tinggi dan android:layout_width untuk lebar. Dalam hal ini, saat Anda membuat ViewGroup, Anda dapat membuat LayoutParams lebih lanjut yang spesifik untuk cara Anda ingin ViewGroup Anda berperilaku.

Android Dilengkapi dengan View dan ViewGroup bawaan yang dapat kita gunakan untuk melakukan banyak tugas umum yang kita butuhkan. Salah satu contoh yang telah kita sebutkan adalah TextView. Itu adalah tampilan sederhana yang dilengkapi dengan aspek yang dapat dikonfigurasi seperti tinggi, lebar, dan ukuran teks. Kita juga memiliki ImageView untuk menampilkan gambar dan EditText, seperti yang telah kita sebutkan, di antara banyak lainnya. Android juga memiliki ViewGroup khusus tempat kita dapat menambahkan Tampilan dan mendapatkan perilaku yang diharapkan.

Tata Letak Linier

LinearLayout memungkinkan kita untuk menambahkan item View ke dalamnya. LinearLayout memiliki atribut orientation yang menentukan bagaimana tata letaknya di layar. Ia juga memiliki LinearLayout.LayoutParams yang menentukan aturan untuk view di dalamnya. Misalnya, atribut android:center_horizontal akan memusatkan view di sepanjang sumbu horizontal, sedangkan android:center_vertical akan memusatkan konten view di sepanjang sumbu vertikal.

Berikut beberapa gambar untuk membantu memahami pemusatan. Kita anggap ini sebagai TextView sederhana di dalam ruang berukuran 200px x 200px; atribut pemusatan akan membuatnya berperilaku seperti berikut.

android:pusat_horizontal

Konten yang Berpusat Secara Horizontal

Konten terpusat secara horizontal

android:pusat_vertikal

Konten yang Terpusat Secara Vertikal

Konten yang berpusat secara vertikal

android:tengah

Konten Terpusat

Konten terpusat

Komponen Inti RecyclerView

Komponen Inti RecyclerView

Komponen Inti RecyclerView

Berikut ini adalah komponen penting RecyclerView:

RecyclerView.Adapter

Dasar #1 โ€“ Pola Adaptor

Adaptor adalah perangkat yang mengubah atribut suatu sistem atau perangkat menjadi atribut perangkat atau sistem lain yang tidak kompatibel. Beberapa adaptor memodifikasi atribut sinyal atau daya, sementara yang lain hanya menyesuaikan bentuk fisik satu konektor dengan konektor lainnya.

Contoh sederhana dalam kehidupan nyata yang menjelaskan fungsi adaptor adalah ketika kita perlu menghubungkan perangkat, tetapi port koneksinya tidak cocok satu sama lain. Ini bisa terjadi ketika Anda mengunjungi negara lain yang menggunakan jenis soket yang berbeda. Jika Anda membawa pengisi daya ponsel atau laptop, akan sulit untuk menghubungkannya ke stopkontak. Namun, Anda tidak akan menyerah, tetapi cukup membeli adaptor yang berada di antara stopkontak dan pengisi daya Anda, sehingga pengisian daya dapat dilakukan.

Hal ini terjadi dalam pemrograman ketika kita ingin menghubungkan dua struktur data untuk menyelesaikan suatu tugas, tetapi port default mereka tidak memiliki cara untuk berkomunikasi satu sama lain.

Kita akan menggunakan contoh sederhana sebuah perangkat dan pengisi daya. Kita akan memiliki dua contoh pengisi daya, satu buatan Amerika dan satu buatan Inggris.

class AmericanCharger() {
    var chargingPower = 10
}
class BritishCharger(){
    var chargingPower = 5
}

Selanjutnya, kita akan membuat dua perangkat.

class AmericanDevice()
class BritishDevice()

Sebagai contoh, kita kemudian dapat membuat beberapa contoh perangkat untuk bermain bersama.

var myAmericanPhone = new AmericanDevice()
var myBritishPhone = new BritishDevice()

Selanjutnya, kita akan memperkenalkan konsep pengisian daya untuk kedua perangkat dengan menambahkan sebuah metode pada perangkat yang bernama charge(). Metode ini menerima pengisi daya masing-masing dan melakukan pengisian daya berdasarkan pengisi daya tersebut.

sealed trait Device
class AmericanDevice : Device{
    fun charge(charger:AmericanCharger){
        //Do some American charging
    }
}
class BritishDevice: Device{
    fun charge(charger:BritishCharger){
        //Do some British charging
    }
}

Dalam hal ini, berdasarkan analogi kita, karena satu dan lain hal kita akan perlu menggunakan BritishCharger saat menggunakan AmericanDevice, atau sebaliknya.

Dalam dunia pemrograman, hal ini biasanya terjadi saat menggabungkan perpustakaan yang menawarkan fungsi yang sama (dalam konteks kami, fungsi bersama kami dikenakan biaya). Kita perlu menemukan cara untuk mengaktifkannya.

Jika kita mengikuti analogi tersebut, kita perlu pergi ke toko elektronik dan membeli adaptor yang memungkinkan kita untuk mengisi daya perangkat Amerika dengan menggunakan pengisi daya Inggris. Dari perspektif pemrograman, kita akan menjadi produsen adaptor tersebut.

Kita akan membuat sebuah adapter yang sesuai dengan pola persis yang kita butuhkan untuk membuat yang lainnya. Kita akan mengimplementasikannya sebagai sebuah kelas sebagai berikut. Tidak harus berupa kelas, bisa juga berupa fungsi yang menyoroti apa yang umumnya dilakukan oleh pola adapter. Kita menggunakan kelas karena sesuai dengan sebagian besar penggunaannya. Android.

class AmericanToBritishChargerAdapter(theAmericanCharger:AmericanCharger){
    fun returnNewCharger(): BritishCharger{
            //convert the American charger to a BritishCharger
            //we would change the American charging functionality
            //to British charging functionality to make sure the
            //adapter doesn't destroy the device. The adapter could
            //, for example, control the power output by dividing by 2
            //our adapter could encompass this functionality in here

           var chargingPower:Int = theAmericanCharger.chargingPower / 2
           var newBritishCharger = new BritishCharger()
           newBritishCharger.chargingPower = theAmericanCharger.chargingPower/2

        return newBritishCharger
    }
}

Dalam dunia pemrograman, perbedaan pada soket analog dengan perbedaan metode yang digunakan untuk pengisian daya. Pengisi daya yang memiliki metode berbeda akan membuat pengisi daya tersebut tidak dapat digunakan.

var myBritishDevice = new BritishDevice()
var americanChargerIFound = new AmericanCharger()

Mencoba memanggil metode charge() pada myBritishDevice dengan americanChargerIFound tidak akan berhasil, karena AmericanDevice hanya menerima AmericanCharger. Jadi, hal ini tidak mungkin dilakukan:

var myBritishDevice = new BritishDevice()
var americanChargerIFound = new AmericanCharger()
myBritishDevice.charge(americanChargerIFound)

Dalam skenario ini, adapter yang telah kita buat, AmericanToBritishChargerAdapter, kini dapat berguna. Kita dapat menggunakan metode returnNewCharger() untuk membuat BritishCharger baru, yang dapat kita gunakan untuk mengisi daya. Yang perlu kita lakukan hanyalah membuat instance dari adapter kita dan memberikannya AmericanCharger yang kita miliki, dan adapter tersebut akan membuat BritishCharger yang dapat kita gunakan.

var myBritishDevice = new BritishDevice()
var americanChargerIFound = new AmericanCharger()
//We create the adapter and feed it the americanCharger
var myAdapter =  AmericanToBritishChargerAdapter(americanChargerIFound)
//calling returnNewCharger from myAdapter would return a BritishCharger
var britishChargerFromAdapter = myAdapter.returnNewCharger()
//and once we have the britishCharger we can now use it
myBritishDevice.charge(britishChargerFromAdapter)

RecyclerView.LayoutManager

Saat berurusan dengan ViewGroup, kita memiliki View yang ditempatkan di dalamnya. LayoutManager bertugas untuk menjelaskan bagaimana View tersebut ditata di dalamnya.

Sebagai perbandingan, saat bekerja dengan ViewGroup LinearLayout, kasus penggunaan yang kita inginkan adalah kemampuan untuk menempatkan item secara vertikal atau horizontal. Ini mudah diimplementasikan dengan menambahkan atribut orientasi, yang memberi tahu kita bagaimana LinearLayout akan ditempatkan di layar. Kita dapat melakukan ini dengan menggunakan android:orientation=VERTICAL|HORIZONTAL atribut.

Kita juga memiliki ViewGroup lain yang disebut GridLayout. Kegunaannya adalah ketika kita ingin menempatkan View dalam struktur grid persegi panjang. Hal ini bisa dilakukan karena alasan seperti membuat data yang kita sajikan kepada pengguna aplikasi mudah dipahami. Secara desain, GridLayout memungkinkan konfigurasi untuk membantu Anda mencapai tujuan ini dengan mendefinisikan dimensi grid; misalnya, kita dapat memiliki grid 4ร—4 atau grid 3ร—2.

RecyclerView.ViewHolder

ViewHolder adalah sebuah abstracKelas ViewHolder juga kita warisi dari RecyclerView. ViewHolder menyediakan metode umum untuk membantu kita merujuk ke View yang telah kita tempatkan di RecyclerView, bahkan setelah mekanisme daur ulang di RecyclerView mengubah berbagai referensi yang tidak kita ketahui.

Daftar Besar

RecyclerView digunakan ketika kita ingin menampilkan sejumlah besar View kepada pengguna, tanpa membebani memori secara berlebihan. RAM di perangkat kami untuk setiap instance Tampilan yang dibuat.

Jika kita mengambil contoh daftar kontak, kita akan memiliki gambaran umum tentang bagaimana tampilan satu kontak dalam daftar tersebut. Yang kemudian akan kita lakukan adalah membuat tata letak templat, yang sebenarnya adalah sebuah View, dengan slot tempat berbagai data dari daftar kontak kita akan diisi. Berikut adalah kode semu yang menjelaskan keseluruhan tujuannya:

//OneContactView
<OneContact>
<TextView>{{PlaceHolderForName}}</TextView>
<TextView>{{PlaceHolderForAddress}}</TextView>
<ImageView>{{PlaceHolderForProfilePicture}}</ImageView>
<TextView>{{PlaceHolderForPhoneNumber}}</TextView>
</OneContact>

Dengan demikian, kita akan memiliki daftar kontak seperti ini:

<ContactList>
</ContactList>

Jika kita memasukkan konten secara manual, kita tidak akan memiliki cara terprogram untuk menambahkan konten baru ke daftar tanpa menulis ulang aplikasi. Untungnya bagi kita, menambahkan View ke ViewGroup didukung oleh sebuah addView(view:View) metode. Meskipun demikian, bukan dengan cara itulah RecyclerView mendapatkan tampilan anak yang ditambahkan ke dalamnya.

Dalam kasus penggunaan kami, kami akan memiliki daftar kontak yang panjang. Untuk setiap kontak dalam daftar, kami perlu membuat OneContactView dan mengisi data di dalam View agar sesuai dengan field di kelas Contact kami. Kemudian setelah kami memiliki view tersebut, kami perlu menambahkannya ke RecyclerView untuk menampilkan daftar tersebut.

data  class Contact(var name:String, var address:String, var pic:String, var phoneNumber:Int)

var contact1 = Contact("Guru","Guru97", "SomePic1.jpg", 991)
var contact2 = Contact("Guru","Guru98", "SomePic2.jpg", 992)
var contact3 = Contact("Guru","Guru99", "SomePic3.jpg", 993)

var myContacts:ArrayList<Contact> = arrayListOf<Contact>(contact1,contact2,contact3)

Kita memiliki serangkaian kontak. OneContactView berisi slot untuk mengambil konten dari kelas Contact dan menampilkannya. Di RecyclerView, kita harus menambahkan View ke dalamnya agar dapat membantu kita dalam kemampuan daur ulangnya.

RecyclerView sebenarnya tidak memungkinkan kita untuk menambahkan tampilan, tetapi memungkinkan kita untuk menambahkan ViewHolder. Jadi, dalam skenario ini, kita memiliki dua bagian yang ingin kita hubungkan tetapi tidak cocok. Di sinilah adapter kita berperan. RecyclerView menyediakan adapter bagi kita, sama seperti pada objek kita. AmericanToBritishChargerAdapter() dari sebelumnya yang memungkinkan kami untuk mengubah AmericanCharger kami, yang tidak dapat digunakan dengan BritishDevice kami, menjadi sesuatu yang dapat digunakan, mirip dengan adaptor daya dalam kehidupan nyata.

Dalam skenario ini, adapter akan mengambil array kontak kita dan View kita, dan dari situ menghasilkan ViewHolder yang bersedia diterima oleh RecyclerView.

RecyclerView menyediakan antarmuka yang dapat kita perluas untuk membuat adapter kita melalui kelas RecyclerView.Adapter. Di dalam adapter ini terdapat cara untuk membuat kelas ViewHolder yang ingin digunakan oleh RecyclerView. Jadi, yang kita miliki adalah situasi yang sama seperti sebelumnya, tetapi dengan satu hal tambahan, yaitu adapter.

Kita memiliki serangkaian kontak, sebuah tampilan untuk menampilkan satu kontak (OneContactView), dan sebuah RecyclerView, yang merupakan daftar View yang menyediakan layanan daur ulang tetapi hanya bersedia menerima ViewHolder. Dalam skenario ini, kita sekarang memiliki kelas RecyclerView.Adapter, yang memiliki metode untuk membuat ViewHolder di dalamnya.

fun createViewHolder(@NonNull parent: ViewGroup, viewType: Int): ViewHolder

RecyclerView.ViewHolder adalah sebuah objek absolut.tracKelas ini menerima View sebagai argumen dan mengubahnya menjadi ViewHolder. Kelas ini menggunakan pola wrapper yang digunakan untuk memperluas kemampuan kelas.

Dasar #2 โ€“ Pola pembungkus

Kita akan menggunakan contoh sederhana untuk menunjukkan bagaimana kita dapat membuat hewan berbicara.

sealed trait Animal{
    fun sound():String
}

data class Cat(name:String):Animal{
    fun sound(){
        "Meow"
        }
}
data class Dog(name:String):Animal{
    fun sound(){
        "Woof"
        }
}

var cat1 = Cat("Tubby")
var dog1 = Dog("Scooby")
cat1.sound() //meow
dog1.sound() //woof

Pada contoh di atas, kita memiliki dua hewan. Jika, secara kebetulan, kita ingin menambahkan metode untuk membuat mereka berbicara, tetapi penulis pustaka tersebut tidak menyenangkan, kita masih dapat menemukan caranya. Yang kita butuhkan adalah pembungkus untuk kelas Hewan kita. Kita akan melakukan ini dengan mengambil Hewan sebagai konstruktor untuk kelas kita.

class SpeechPoweredAnimalByWrapper(var myAnimal:Animal){

    fun sound(){
        myAnimal.sound()
    }

    fun speak(){
        println("Hello, my name is ${myAnimal.name}")
    }
}

Sekarang kita dapat meneruskan instance hewan ke SpeechPoweredAnimalByWrapper. Memanggil metode sound() padanya akan memanggil metode sound() hewan yang diteruskan. Kita juga memiliki metode speak() tambahan, yang dihitung sebagai fungsionalitas baru yang kita tambahkan ke hewan yang diteruskan. Kita dapat menggunakannya sebagai berikut:

var cat1 =  Cat("Garfield")
cat1.sound()//"meow"
cat1.speak()// doesn't work as it isn't implemented
var talkingCat = new SpeechPoweredAnimalByWrapper(cat1)
talkingCat.sound() //"meow" the sound method calls the one defined for cat1
talkingCat.speak() //"Hello, my name is Garfield"

Dengan menggunakan pola ini, kita dapat mengambil kelas dan menambahkan fungsionalitas. Yang kita butuhkan hanyalah meneruskan instance kelas dan metode baru yang didefinisikan oleh pembungkus kita.ping kelas.

Pada kasus di atas, kita menggunakan kelas konkret. Hal yang sama juga dapat diimplementasikan dalam sebuah abstrak.tracKelas t. Kita perlu mengubah kelas SpeechPoweredAnimalByWrapper menjadi abs.tract, dan selesai. Kita akan mengubah nama kelas menjadi sesuatu yang lebih pendek agar lebih mudah dibaca.

abstract class SpeechPowered(var myAnimal:Animal){

    fun sound(){
        myAnimal.sound()
    }

    fun speak(){
        println("Hello, my name is ${myAnimal.name}")
    }
}

Sama seperti sebelumnya, tetapi artinya akan berbeda. Dalam kelas biasa, kita dapat memiliki instance dari sebuah kelas dengan cara yang sama seperti kita membuat cat1 dan dog1. AbstracNamun, kelas t tidak dimaksudkan untuk diinstansiasi tetapi dimaksudkan untuk memperluas kelas lain. Jadi bagaimana kita akan menggunakan SpeechPowered(var myAnimal:Animal) abs yang baru?tracKelas t? Kita dapat menggunakannya dengan membuat kelas-kelas baru yang akan memperluasnya dan, pada gilirannya, memperoleh fungsionalitasnya.

Dalam contoh kita, kita akan membuat kelas SpeechPoweredAnimal yang memperluas kelas tersebut.

class SpeechPoweredAnimal(var myAnimal:Animal):SpeechPowered(myAnimal)
var cat1 =  Cat("Tubby")
var speakingKitty = SpeechPoweredAnimal(cat1)
speakingKitty.speak() //"Hello, my name is Tubby"

Ini adalah pola yang sama yang digunakan di ViewHolder. Kelas RecyclerView.ViewHolder adalah sebuah abstracKelas t yang menambahkan fungsionalitas ke View, sama seperti kita menambahkan metode speak ke hewan. Fungsionalitas tambahan inilah yang membuatnya berfungsi saat berurusan dengan RecyclerView.

Beginilah cara kita membuat OneContactViewHolder dari OneContactView:

//The View argument we pass is converted to a ViewHolder which uses the View to give it more abilities and in turn work with the RecyclerView
class OneContactViewHolder(ourContactView: View) : RecyclerView.ViewHolder(ourContactView)

RecyclerView memiliki adapter yang memungkinkan kita untuk menghubungkan array kontak kita ke ContactsView dengan RecyclerView.

Menambahkan Tampilan

ViewGroup tidak menggambar ulang secara otomatis tetapi mengikuti jadwal tertentu. Mungkin saja pada perangkat Anda, ViewGroup menggambar ulang setiap 10ms atau 100ms; atau, jika kita memilih angka yang tidak masuk akal, misalnya 1 menit, ketika kita menambahkan View ke ViewGroup, Anda akan melihat perubahannya 1 menit kemudian ketika ViewGroup "diperbarui".

RecyclerView.Pendaur Ulang

Persiapan #3 โ€“ Penyimpanan

Salah satu contoh terbaik di mana kita secara teratur melakukan penyegaran adalah di peramban. Bayangkan, misalnya, situs yang kita kunjungi bersifat statis dan tidak mengirimkan konten secara dinamis; kita perlu terus menyegarkan halaman untuk melihat perubahannya.

Untuk contoh ini, mari kita bayangkan situs yang dimaksud adalah Twitter. Kita akan memiliki serangkaian tweet statis yang terdaftar, dan satu-satunya cara kita dapat melihat tweet baru adalah dengan mengklik tombol refresh untuk mengambil ulang konten.

Memperbarui seluruh layar jelas merupakan hal yang mahal. Bayangkan jika kita memiliki bandwidth terbatas dari penyedia layanan telepon kita, dan daftar tweet kita memiliki banyak gambar dan video; akan sangat mahal untuk mengunduh ulang semua konten halaman setiap kali kita me-refresh halaman.

Kita memerlukan cara untuk menyimpan tweet yang sudah dimuat dan memastikan permintaan berikutnya dapat mengetahui tweet mana yang sudah dimilikinya. Oleh karena itu, sistem tidak akan mengunduh ulang semuanya, melainkan hanya mengambil tweet baru, dan juga memeriksa apakah beberapa tweet yang telah disimpan secara lokal sudah tidak ada lagi sehingga dapat dihapus secara lokal. Apa yang kita jelaskan ini disebut caching.

Informasi yang kami kirimkan ke situs web tentang konten yang kami miliki disebut metadata. Jadi, dalam arti sebenarnya, kami tidak hanya mengatakan "kami ingin memuat situs Anda," tetapi kami mengatakan "kami ingin memuat situs Anda, dan berikut adalah beberapa konten yang telah kami simpan dari pemuatan terakhir; silakan gunakan ini untuk hanya mengirimkan kepada kami apa yang belum ada di sana, sehingga kami tidak menggunakan banyak bandwidth."

Panggilan Tata Letak โ€“ Daftar Tweet pasti gila

Salah satu contoh panggilan layout adalah scrollToPosition. Ini adalah contoh umum yang terdapat pada aplikasi seperti aplikasi obrolan. Jika seseorang dalam percakapan membalas gelembung obrolan sebelumnya, beberapa aplikasi obrolan menyertakan balasan dan tautan ke gelembung obrolan tersebut, yang setelah diklik akan mengarahkan Anda ke tempat pesan asli Anda berada.

Dalam kasus di mana kita memanggil metode ini sebelum kita menambahkan LayoutManager ke RecyclerView kita dan sebelum kita memiliki RecyclerView.Adapter, scrollToPosition(n:Int) akan diabaikan begitu saja.

Komunikasi antar Komponen RecyclerView

Persiapan #4 โ€“ Panggilan Balik

Dalam menjalankan fungsinya, RecyclerView memiliki banyak komponen yang bergerak. Ia harus berurusan dengan LayoutManager, yang memberi tahu kita cara mengatur View, baik secara linear maupun dalam bentuk grid. Ia juga harus berurusan dengan adapter yang bertugas mengubah item kita (contactList) menjadi View (OneContactView) dan kemudian menjadi ViewHolder (OneContactViewHolder) yang siap digunakan oleh RecyclerView menggunakan metode yang disediakannya.

Bahan baku untuk RecyclerView adalah View kita, misalnya OneContactView, dan sumber data.

contactList:Array<Contact>

Kami menggunakan skenario sederhana sebagai titik awal untuk memahami apa yang ingin dicapai oleh RecyclerView. Kasus dasar ketika kita memiliki array statis berisi 1000 kontak yang ingin kita tampilkan kepada pengguna mudah dipahami. Mekanisme RecyclerView benar-benar mulai bekerja ketika daftar tersebut tidak lagi statis. Dengan daftar dinamis, kita harus memikirkan apa yang terjadi pada Tampilan di layar ketika kita menambahkan item ke daftar atau menghapus item dari daftar.

RecyclerView.LayoutManager

Selain menentukan bagaimana tampilan kita disusun, baik secara linier atau dalam bentuk grid, LayoutManager melakukan banyak pekerjaan di balik layar untuk membantu...ping Pihak pendaur ulang tahu kapan harus melakukan daur ulang.

Ia bertanggung jawab untuk menjagaping tracLayoutManager mengelola k dari View yang saat ini terlihat di layar dan mengkomunikasikan informasi ini ke mekanisme daur ulang. Saat pengguna menggulir ke bawah, LayoutManager bertanggung jawab untuk memberi tahu sistem daur ulang tentang View yang kehilangan fokus di bagian atas sehingga dapat digunakan kembali, alih-alih tetap di sana dan mengonsumsi memori atau dihancurkan hanya untuk membuat yang baru.

Ini berarti LayoutManager perlu menyimpan track dari posisi pengguna saat mereka menggulir daftar kita. Ini dilakukan dengan memiliki daftar posisi yang berbasis indeks, yaitu item pertama dimulai dari 0 dan meningkat sesuai dengan jumlah item dalam daftar kita.

Jika kita dapat melihat 10 item dalam daftar kita yang berjumlah, katakanlah, 100, pada awalnya LayoutManager menyadari bahwa ia sedang memfokuskan View-0 hingga View-9. Saat kita menggulir, LayoutManager dapat menghitung tampilan mana yang kehilangan fokus.

LayoutManager mampu melepaskan tampilan-tampilan ini ke mekanisme daur ulang sehingga dapat digunakan kembali (data baru dapat diikatkan padanya; misalnya data kontak suatu Tampilan dapat dihapus dan data kontak baru dari segmen berikutnya dapat menggantikan placeholder).

Ini akan menjadi kasus yang menyenangkan jika daftar yang kita miliki bersifat statis, tetapi salah satu kasus penggunaan RecyclerView yang paling umum adalah dengan daftar dinamis di mana data dapat berasal dari titik akhir daring atau bahkan mungkin dari sensor. Data tidak hanya ditambahkan, tetapi data pada daftar kita terkadang dihapus atau diperbarui.

Keadaan data kita yang dinamis dapat membuat pemahaman tentang LayoutManager menjadi sangat sulit. Karena alasan ini, LayoutManager menyimpan daftar item dan posisinya sendiri, terpisah dari daftar yang digunakan oleh komponen daur ulang. Hal ini memastikan bahwa LayoutManager menjalankan tugas tata letaknya dengan benar.

Pada saat yang sama, LayoutManager dari RecyclerView tidak ingin salah merepresentasikan data yang dimilikinya. Agar dapat beroperasi dengan benar, LayoutManager melakukan sinkronisasi dengan RecyclerView.Adapter pada interval tertentu (60ms), berbagi informasi tentang item daftar kita, yaitu item yang ditambahkan, diperbarui, dihapus, atau dipindahkan dari satu posisi ke posisi lain. LayoutManager, setelah menerima informasi ini, mengatur ulang konten di layar agar sesuai dengan perubahan jika diperlukan.

Banyak operasi inti yang berkaitan dengan RecyclerView berputar di sekitar komunikasi antara RecyclerView.LayoutManager dan RecyclerView.Adapter yang menyimpan daftar data kita, yang terkadang statis atau terkadang dinamis.

Selain itu, RecyclerView menyediakan metode yang dapat kita gunakan untuk mendengarkan peristiwa, seperti onBindViewHolder ketika RecyclerView.Adapter kita mengikat konten dari daftar kita (misalnya kontak) ke ViewHolder sehingga digunakan untuk menampilkan informasi di layar.

Yang lainnya adalah onCreateViewHolder, yang memberi tahu kita kapan RecyclerView.Adapter mengambil View biasa seperti OneContactView dan mengubahnya menjadi item ViewHolder yang dapat digunakan oleh RecyclerView.

Selain mekanisme inti yang memungkinkan daur ulang, RecyclerView menyediakan cara untuk menyesuaikan perilaku tanpa memengaruhi daur ulang. Penggunaan kembali View membuat sulit untuk melakukan hal-hal umum yang biasa kita lakukan dengan view statis, seperti bereaksi terhadap event onClick.

Seperti yang kita ketahui, RecyclerView.LayoutManager yang menyajikan Tampilan kepada pengguna mungkin sejenak memiliki daftar item yang berbeda dari RecyclerView.Adapter yang menyimpan daftar tersebut dalam basis data atau mengalir dari sumber. Menempatkan event OnClick langsung pada View dapat menyebabkan perilaku yang tidak terduga, seperti menghapus kontak yang salah.

Gradle

Jika kita ingin menggunakan RecyclerView, kita perlu menambahkannya sebagai dependensi di file build.gradle kita. Pada contoh berikut, kita telah menggunakan `implementation โ€œandroidx.recyclerview:recyclerview:1.1.0โ€`, yang merupakan versi terbaru sesuai artikel ini.

Setelah menambahkan ketergantungan ke kami Gradle file, kita akan diminta oleh Android Studio untuk menyinkronkan perubahan. Beginilah cara kami Gradle File ini akan menangani penambahan RecyclerView di proyek kosong hanya dengan pengaturan default.

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.2"
    defaultConfig {
        applicationId "com.guru99.learnrecycler"
        minSdkVersion 17
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
             'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.core:core-ktx:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

    implementation "androidx.recyclerview:recyclerview:1.1.0"
}

Saat ini kita hanya memiliki satu file layout. Kita akan mulai dengan contoh sederhana di mana kita menggunakan RecyclerView untuk menampilkan daftar nama buah di layar.

Daftar barang

Kita akan masuk ke file MainActivity dan membuat array berisi nama-nama buah, tepat sebelum metode onCreate() yang dibuat saat pengaturan awal.

package com.guru99.learnrecycler

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

class MainActivity : AppCompatActivity() {

    var fruitNames:Array<String> = arrayOf<String>("Banana", "Mango", "Passion fruit", "Orange", "Grape")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

Tujuan kita selanjutnya adalah menampilkan daftar ini di layar menggunakan RecyclerView. Untuk melakukan ini, kita akan masuk ke direktori layout yang berisi layout kita dan membuat View yang akan bertanggung jawab untuk menampilkan satu buah.

Tata letak yang akan digunakan untuk setiap item dalam daftar kami

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/fruitName"
    />
</TextView>

Pada TextView di atas, kita telah menambahkan kolom id yang akan digunakan untuk mengidentifikasi sebuah View. Kolom ini tidak dibuat secara default. Kita telah memberikan TextView kita id fruitName agar sesuai dengan data yang akan terikat padanya.

Menambahkan RecyclerView ke tata letak utama

Dalam aktivitas yang sama, terdapat file layout main_layout.xml yang dibuat secara default untuk kita. Jika kita memilih proyek kosong, maka akan dibuatkan file tersebut. XML RecyclerView akan berisi ConstraintLayout dan di dalamnya terdapat TextView dengan teks โ€œHelloโ€. Kita akan menghapus semua konten dan hanya menyisakan RecyclerView di dalam layout seperti di bawah ini:

<?xml version="1.0" encoding="utf-8"?>
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/fruitRecyclerView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" />

Kami juga telah menambahkan atribut id untuk RecyclerView, yang akan kami gunakan untuk merujuknya dalam kode kami.

android:id="@+id/fruitRecyclerView"

Selanjutnya, kita akan kembali ke file MainActivity kita. Dengan menggunakan id yang telah kita buat, kita dapat merujuk ke View yang baru saja kita buat. Kita akan mulai dengan merujuk ke RecyclerView menggunakan metode findViewById() yang disediakan oleh AndroidKita akan melakukan ini di dalam metode onCreate(). Metode onCreate() kita akan terlihat seperti berikut.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    var myFruitRecyclerView: RecyclerView = findViewById(R.id.fruitRecyclerView)
}

Buat ViewHolder

Selanjutnya, kita akan membuat RecyclerView.ViewHolder, yang bertanggung jawab untuk mengambil View kita dan mengubahnya menjadi ViewHolder, yang digunakan RecyclerView untuk menampilkan item kita. Kita akan melakukan ini tepat setelah metode onCreate().

package com.guru99.learnrecycler

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import androidx.recyclerview.widget.RecyclerView

class MainActivity : AppCompatActivity() {

    var fruitNames:Array<String> = arrayOf<String>("Banana", "Mango", "Passion fruit", "Orange", "Grape")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var myFruitRecyclerView: RecyclerView = findViewById(R.id.fruitRecyclerView)
    }

    class FruitViewHolder(fruitView: View): RecyclerView.ViewHolder(fruitView)

}

Buat RecyclerViewAdapter

Selanjutnya, kita akan membuat kelas FruitArrayAdapter yang memperluas kelas RecyclerView.Adapter. FruitArrayAdapter yang kita buat akan bertanggung jawab atas hal-hal berikut: mengambil nama buah dari array buah, membuat ViewHolder menggunakan tampilan one_fruit_view.xml kita, kemudian mengikat buah ke ViewHolder dan secara dinamis mengikat konten ke View yang telah kita buat.

package com.guru99.learnrecycler

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import androidx.recyclerview.widget.RecyclerView

class MainActivity : AppCompatActivity() {

    var fruitNames:Array<String> = arrayOf<String>("Banana", "Mango", "Passion fruit", "Orange", "Grape")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var myFruitRecyclerView: RecyclerView = findViewById(R.id.fruitRecyclerView)
    }

    class FruitViewHolder(fruitView: View): RecyclerView.ViewHolder(fruitView)

    class FruitArrayAdapter(var fruitArray: Array<String>) : RecyclerView.Adapter<FruitViewHolder>()
}

Android Studio akan menambahkan garis bergelombang merah pada FruitArrayAdapter kita, yang memberi tahu kita bahwa kita perlu mengimplementasikan metode yang dapat digunakan RecyclerView untuk menghubungkan array kita ke ViewHolder.

class FruitListAdapter(var fruitArray: Array<String>) : RecyclerView.Adapter<FruitViewHolder>() {
     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FruitViewHolder {

     }

     override fun getItemCount(): Int {

     }

     override fun onBindViewHolder(holder: FruitViewHolder, position: Int) {

     }
 }

Kita akan mulai dengan bagian termudah dari kode yang dihasilkan, yaitu metode getItemCount(). Kita tahu cara mendapatkan jumlah item dalam array kita dengan memanggil properti size array.

class FruitListAdapter(var fruitArray: Array<String>) : RecyclerView.Adapter<FruitViewHolder>() {
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FruitViewHolder {

        }

        override fun getItemCount(): Int {
         return fruitArray.size
        }

        override fun onBindViewHolder(holder: FruitViewHolder, position: Int) {

        }
    }

Kemudian kita akan mengimplementasikan metode onCreateViewHolder. Di sinilah RecyclerView meminta kita untuk membantunya membuat FruitViewHolder. Jika kita ingat, beginilah tampilan kelas FruitViewHolder kita:

class FruitViewHolder(fruitView: View): RecyclerView.ViewHolder(fruitView)

Hal ini membutuhkan fruitView kita, yang telah kita buat sebagai file XML one_fruit_view.xml. Kita dapat membuat referensi ke XML ini dan mengonversinya menjadi View sebagai berikut.

class FruitListAdapter(var fruitArray: Array<String>) : RecyclerView.Adapter<FruitViewHolder>() {

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FruitViewHolder {

            var fruitView = LayoutInflater.from(parent.context).inflate(R.layout.one_fruit_view, parent, false)

            var fruitViewHolder = FruitViewHolder(fruitView)

            return fruitViewHolder

        }

        override fun getItemCount(): Int {
            return fruitArray.size
        }

        override fun onBindViewHolder(holder: FruitViewHolder, position: Int) {

        }
    }

Bagian yang tersisa adalah penggantian pada onBindViewHolder.

fun onBindViewHolder(holder: FruitViewHolder, position: Int)

RecyclerView.Adapter meminta nilai integer posisi, yang kita gunakan untuk mengambil item dari daftar kita. Ia juga menyediakan holder sehingga kita dapat mengikat item yang kita dapatkan dari fruitArray ke View yang berada di dalam view holder tersebut. View yang berada di dalam ViewHolder dapat diakses melalui field ViewHolder.itemView. Setelah kita mendapatkan view tersebut, kita dapat menggunakan id fruitName yang telah kita buat sebelumnya untuk mengatur kontennya.

override fun onBindViewHolder(holder: FruitViewHolder, position: Int) {

          var ourFruitTextView = holder.itemView.findViewById<TextView>(R.id.fruitName)

          var aFruitName = fruitArray.get(position)

          ourFruitTextView.setText(aFruitName)
      }

Dengan demikian, FruitArrayAdapter kita sudah lengkap dan tampilannya seperti berikut.

class FruitListAdapter(var fruitArray: Array<String>) : RecyclerView.Adapter<FruitViewHolder>() {

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FruitViewHolder {

            var fruitView = LayoutInflater.from(parent.context).inflate(R.layout.one_fruit_view, parent, false)

            var fruitViewHolder = FruitViewHolder(fruitView)

            return fruitViewHolder
        }

        override fun getItemCount(): Int {
            return fruitArray.size
        }

        override fun onBindViewHolder(holder: FruitViewHolder, position: Int) {

            var ourFruitTextView = holder.itemView.findViewById<TextView>(R.id.fruitName)

            var aFruitName = fruitArray.get(position)

            ourFruitTextView.setText(aFruitName)
        }
    }

Terakhir, kita siap untuk menghubungkan bagian-bagian yang tersisa dari RecyclerView kita, yaitu membuat LayoutManager yang akan memberi tahu RecyclerView cara menampilkan isi daftar, apakah akan ditampilkan secara linear menggunakan LinearLayoutManager atau dalam bentuk grid menggunakan GridLayoutManager atau StaggeredGridLayoutManager.

Buat Manajer Tata Letak

Kita akan kembali ke dalam fungsi onCreate dan menambahkan LayoutManager.

override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.activity_main)

       var myFruitRecyclerView: RecyclerView = findViewById(R.id.fruitRecyclerView)

       var fruitLinearLayout = LinearLayoutManager(this)

       myFruitRecyclerView.layoutManager =fruitLinearLayout

   }

Kaitkan adaptor kita ke item dan atur di RecyclerView

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var myFruitRecyclerView: RecyclerView = findViewById(R.id.fruitRecyclerView)

        var fruitLinearLayout = LinearLayoutManager(this)

        myFruitRecyclerView.layoutManager =fruitLinearLayout

        var fruitListAdapter = FruitListAdapter(fruitNames)

        myFruitRecyclerView.adapter =fruitListAdapter
    }

Kami juga telah membuat instance fruitListAdapter dan memberinya array nama buah. Dan pada dasarnya, kita sudah selesai. File MainActivity.kt lengkapnya terlihat seperti berikut.

package com.guru99.learnrecycler

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView

class MainActivity : AppCompatActivity() {

    var fruitNames:Array<String> = arrayOf<String>("Banana", "Mango", "Passion fruit", "Orange", "Grape")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var myFruitRecyclerView: RecyclerView = findViewById(R.id.fruitRecyclerView)

        var fruitLinearLayout = LinearLayoutManager(this)

        myFruitRecyclerView.layoutManager =fruitLinearLayout

        var fruitListAdapter = FruitListAdapter(fruitNames)

        myFruitRecyclerView.adapter =fruitListAdapter
    }

    class FruitViewHolder(fruitView: View): RecyclerView.ViewHolder(fruitView)

    class FruitListAdapter(var fruitArray: Array<String>) : RecyclerView.Adapter<FruitViewHolder>() {

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): FruitViewHolder {

            var fruitView = LayoutInflater.from(parent.context).inflate(R.layout.one_fruit_view, parent, false)

            var fruitViewHolder = FruitViewHolder(fruitView)

            return fruitViewHolder
        }

        override fun getItemCount(): Int {
            return fruitArray.size
        }

        override fun onBindViewHolder(holder: FruitViewHolder, position: Int) {

            var ourFruitTextView = holder.itemView.findViewById<TextView>(R.id.fruitName)

            var aFruitName = fruitArray.get(position)

            ourFruitTextView.setText(aFruitName)
        }
    }
}

Unduh Proyek

Pertanyaan Umum Demo Slot

RecyclerView adalah penerus ListView yang lebih fleksibel dan efisien. Ia menerapkan pola ViewHolder, mendukung tata letak linier, grid, dan bertingkat melalui pengelola tata letak, serta menambahkan animasi item bawaan, sementara ListView tidak menawarkan satupun fitur tersebut secara default.

GridView hanya menampilkan item dalam grid tetap. RecyclerView dapat mereproduksi grid menggunakan GridLayoutManager, tetapi juga mendukung tata letak linier dan bertingkat, daur ulang tampilan, dan animasi, sehingga jauh lebih serbaguna daripada GridView.

Contoh RecyclerView ini ditulis dalam Kotlin, bahasa yang secara resmi direkomendasikan oleh Google untuk Android pengembangan. API RecyclerView, adapter, dan layout manager yang sama juga berfungsi di Java.

Lampirkan pendengar klik di dalam ViewHolder atau onBindViewHolder, lalu ekspos melalui callback antarmuka ke aktivitas atau fragmen. Menggunakan posisi ViewHolder menghindari pengikatan klik ke item daur ulang yang salah.

DiffUtil adalah kelas utilitas yang menghitung perbedaan antara dua daftar dan mengirimkan serangkaian pembaruan minimal ke adaptor. Ini membuat perubahan daftar dinamis menjadi efisien dan secara otomatis menganimasikan penambahan, penghapusan, dan pemindahan.

Jetpack Compose menggunakan LazyColumn dan LazyRow sebagai pengganti RecyclerView untuk layar baru. Namun, RecyclerView tetap banyak digunakan dalam proyek berbasis View yang sudah ada dan dapat disematkan di dalam Compose melalui API interoperabilitas.

Ya. Asisten AI seperti GitHub Copilot dan alat berbasis GPT dapat membuat kerangka dasar adapter RecyclerView, ViewHolder, dan onBindViewHolder dari perintah singkat. Pengembang tetap harus meninjau kode yang dihasilkan untuk memastikan kebenaran dan kinerjanya.

Pembelajaran mesin Android Aplikasi menggunakan RecyclerView untuk menampilkan output dinamis seperti rekomendasi, peringkat pencarian, atau klasifikasi gambar. Adapter mengikat hasil model ke item daftar sehingga dataset yang besar dan sering berubah dapat digulir dengan lancar.

Ringkaslah postingan ini dengan: