Bergabunglah bersama kami di ⁠#Android11: The Beta Launch Show pada tanggal 3 Juni!

Membuat Daftar dengan RecyclerView

Membuat daftar dengan RecyclerView   Bagian dari Android Jetpack.

Jika aplikasi Anda perlu menampilkan daftar scroll elemen yang didasarkan pada set data berukuran besar (atau data yang sering berubah), sebaiknya gunakan RecyclerView seperti yang dijelaskan di halaman ini.

Tips: Mulailah dengan kode template di Android Studio dengan mengklik File > New > Fragment > Fragment (List). Lalu tambahkan fragmen tersebut ke tata letak aktivitas Anda.

Gambar 1. Daftar yang menggunakan RecyclerView

Gambar 2. Daftar yang juga menggunakan CardView

Jika Anda ingin membuat daftar yang menampilkan kartu, seperti ditunjukkan dalam gambar 2, gunakan juga CardView widget seperti yang dijelaskan dalam Membuat Tata Letak Berbasis Kartu.

Jika ingin melihat beberapa contoh kode untuk RecyclerView, periksa Contoh Aplikasi RecyclerView Java | Kotlin.

Ringkasan RecyclerView

Widget RecyclerView adalah versi yang lebih canggih dan fleksibel dari ListView.

Dalam model RecyclerView ini, beberapa komponen berbeda bekerja sama untuk menampilkan data Anda. Container keseluruhan untuk antarmuka pengguna Anda adalah objek RecyclerView yang ditambahkan ke tata letak Anda. RecyclerView terisi otomatis dengan tampilan yang disediakan oleh pengelola tata letak yang Anda tentukan. Anda dapat menggunakan salah satu pengelola tata letak standar kami (seperti LinearLayoutManager atau GridLayoutManager), atau mengimplementasikan pengelola tata letak Anda sendiri.

Tampilan dalam daftar diwakili oleh objek penampung tampilan. Objek ini adalah instance dari class yang ditentukan dengan memperluas RecyclerView.ViewHolder. Setiap penampung tampilan bertugas menampilkan satu item di sebuah tampilan. Misalnya, jika daftar Anda berisi koleksi musik, setiap penampung tampilan dapat mewakili satu album. RecyclerView hanya membuat penampung tampilan sebanyak yang diperlukan untuk menampilkan bagian konten dinamis yang muncul di layar, plus beberapa tambahan. Saat pengguna men-scroll daftar, RecyclerView akan mengambil tampilan yang berada di luar layar dan mengikatnya kembali ke data yang sedang di-scroll di layar.

Objek penampung tampilan dikelola oleh sebuah adaptor yang dibuat dengan memperluas RecyclerView.Adapter. Adaptor ini membuat penampung tampilan sesuai kebutuhan. Adaptor juga mengikat penampung tampilan ke data. Hal ini dilakukan dengan menetapkan penampung tampilan ke sebuah posisi, lalu memanggil metode onBindViewHolder() adaptor. Metode tersebut menggunakan posisi penampung tampilan untuk menentukan apa kontennya, berdasarkan posisi daftarnya.

Model RecyclerView ini melakukan banyak tugas pengoptimalan sehingga Anda tidak perlu menanganinya:

  • Saat daftar diisi untuk pertama kalinya, model ini akan membuat dan mengikat beberapa penampung tampilan di salah satu sisi daftar. Misalnya, jika tampilan menampilkan posisi daftar 0 sampai 9, maka RecyclerView akan membuat dan mengikat penampung tampilan tersebut, dan mungkin juga membuat dan mengikat penampung tampilan untuk posisi 10. Dengan begitu, jika pengguna men-scroll daftar, elemen berikutnya akan siap ditampilkan.
  • Saat pengguna men-scroll daftar, RecyclerView akan membuat penampung tampilan baru sesuai keperluan. Widget ini juga menyimpan tampilan yang telah di-scroll keluar layar, sehingga dapat digunakan kembali. Jika pengguna mengubah arah scroll, penampung tampilan yang di-scroll keluar layar dapat dikembalikan lagi ke layar. Di sisi lain, jika pengguna terus men-scroll dalam arah yang sama, penampung tampilan yang telah berada di luar layar paling lama dapat diikat kembali ke data baru. Penampung tampilan tidak perlu dibuat atau diluaskan tampilannya. Aplikasi cukup memperbarui konten tampilan agar cocok dengan item baru tempatnya diikatkan.
  • Saat item yang ditampilkan berubah, Anda dapat memberi tahu adaptor dengan memanggil metode RecyclerView.Adapter.notify…() yang sesuai. Selanjutnya, kode bawaan adaptor akan mengikat kembali item yang terpengaruh saja.

Menambahkan support library

Untuk mengakses widget RecyclerView, Anda perlu menambahkan Support Library V7 ke project Anda sebagai berikut:

  1. Buka file build.gradle untuk modul aplikasi Anda.
  2. Tambahkan support library ke bagian dependencies.
        dependencies {
            implementation 'com.android.support:recyclerview-v7:28.0.0'
        }
        

Menambahkan RecyclerView ke tata letak

Kini Anda dapat menambahkan RecyclerView ke file tata letak. Misalnya, tata letak berikut menggunakan RecyclerView sebagai satu-satunya tampilan untuk seluruh tata letak:

    <?xml version="1.0" encoding="utf-8"?>
    <!-- A RecyclerView with some commonly used attributes -->
    <android.support.v7.widget.RecyclerView
        android:id="@+id/my_recycler_view"
        android:scrollbars="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
    

Setelah Anda menambahkan widget RecyclerView ke tata letak, dapatkan handle objek, hubungkan ke pengelola tata letak, dan tambahkan adaptor untuk data yang akan ditampilkan:

Kotlin

    class MyActivity : Activity() {
        private lateinit var recyclerView: RecyclerView
        private lateinit var viewAdapter: RecyclerView.Adapter<*>
        private lateinit var viewManager: RecyclerView.LayoutManager

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

            viewManager = LinearLayoutManager(this)
            viewAdapter = MyAdapter(myDataset)

            recyclerView = findViewById<RecyclerView>(R.id.my_recycler_view).apply {
                // use this setting to improve performance if you know that changes
                // in content do not change the layout size of the RecyclerView
                setHasFixedSize(true)

                // use a linear layout manager
                layoutManager = viewManager

                // specify an viewAdapter (see also next example)
                adapter = viewAdapter

            }
        }
        // ...
    }
    

Java

    public class MyActivity extends Activity {
        private RecyclerView recyclerView;
        private RecyclerView.Adapter mAdapter;
        private RecyclerView.LayoutManager layoutManager;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.my_activity);
            recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);

            // use this setting to improve performance if you know that changes
            // in content do not change the layout size of the RecyclerView
            recyclerView.setHasFixedSize(true);

            // use a linear layout manager
            layoutManager = new LinearLayoutManager(this);
            recyclerView.setLayoutManager(layoutManager);

            // specify an adapter (see also next example)
            mAdapter = new MyAdapter(myDataset);
            recyclerView.setAdapter(mAdapter);
        }
        // ...
    }
    

Menambahkan adaptor daftar

Untuk memasukkan semua data Anda ke daftar, Anda harus memperluas class RecyclerView.Adapter. Objek ini membuat tampilan untuk item, dan mengganti konten sebagian tampilan dengan item data baru ketika item asli tidak lagi terlihat.

Contoh kode berikut menunjukkan implementasi sederhana untuk set data yang terdiri dari array string yang ditampilkan menggunakan widget TextView:

Kotlin

    class MyAdapter(private val myDataset: Array<String>) :
            RecyclerView.Adapter<MyAdapter.MyViewHolder>() {

        // Provide a reference to the views for each data item
        // Complex data items may need more than one view per item, and
        // you provide access to all the views for a data item in a view holder.
        // Each data item is just a string in this case that is shown in a TextView.
        class MyViewHolder(val textView: TextView) : RecyclerView.ViewHolder(textView)

        // Create new views (invoked by the layout manager)
        override fun onCreateViewHolder(parent: ViewGroup,
                                        viewType: Int): MyAdapter.MyViewHolder {
            // create a new view
            val textView = LayoutInflater.from(parent.context)
                    .inflate(R.layout.my_text_view, parent, false) as TextView
            // set the view's size, margins, paddings and layout parameters
            ...
            return MyViewHolder(textView)
        }

        // Replace the contents of a view (invoked by the layout manager)
        override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
            // - get element from your dataset at this position
            // - replace the contents of the view with that element
            holder.textView.text = myDataset[position]
        }

        // Return the size of your dataset (invoked by the layout manager)
        override fun getItemCount() = myDataset.size
    }
    

Java

    public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
        private String[] mDataset;

        // Provide a reference to the views for each data item
        // Complex data items may need more than one view per item, and
        // you provide access to all the views for a data item in a view holder
        public static class MyViewHolder extends RecyclerView.ViewHolder {
            // each data item is just a string in this case
            public TextView textView;
            public MyViewHolder(TextView v) {
                super(v);
                textView = v;
            }
        }

        // Provide a suitable constructor (depends on the kind of dataset)
        public MyAdapter(String[] myDataset) {
            mDataset = myDataset;
        }

        // Create new views (invoked by the layout manager)
        @Override
        public MyAdapter.MyViewHolder onCreateViewHolder(ViewGroup parent,
                                                       int viewType) {
            // create a new view
            TextView v = (TextView) LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.my_text_view, parent, false);
            ...
            MyViewHolder vh = new MyViewHolder(v);
            return vh;
        }

        // Replace the contents of a view (invoked by the layout manager)
        @Override
        public void onBindViewHolder(MyViewHolder holder, int position) {
            // - get element from your dataset at this position
            // - replace the contents of the view with that element
            holder.textView.setText(mDataset[position]);

        }

        // Return the size of your dataset (invoked by the layout manager)
        @Override
        public int getItemCount() {
            return mDataset.length;
        }
    }
    

Pengelola tata letak memanggil metode onCreateViewHolder() adaptor. Metode tersebut harus menyusun RecyclerView.ViewHolder dan menyetel tampilan yang digunakannya untuk menampilkan kontennya. Jenis ViewHolder harus cocok dengan jenis yang dideklarasikan dalam tanda tangan class Adaptor. Biasanya, jenis ini akan menetapkan tampilan dengan meluaskan file tata letak XML. Karena penampung tampilan belum ditetapkan ke data tertentu mana pun, metode ini tidak benar-benar menetapkan konten tampilan.

Pengelola tata letak kemudian mengikat penampung tampilan ke datanya. Hal ini dilakukan dengan memanggil metode onBindViewHolder() adaptor, dan memasukkan posisi penampung tampilan di RecyclerView. Metode onBindViewHolder() perlu mengambil data yang sesuai, dan menggunakannya untuk mengisi tata letak penampung tampilan. Misalnya, jika RecyclerView menampilkan daftar nama, metode ini mungkin menemukan nama yang sesuai di dalam daftar, dan mengisikannya di widget TextView penampung tampilan.

Jika daftar perlu diperbarui, panggil metode notifikasi pada objek RecyclerView.Adapter, seperti notifyItemChanged(). Selanjutnya, pengelola tata letak mengikat kembali semua penampung tampilan yang terpengaruh, sehingga datanya dapat diperbarui.

Tips: Class ListAdapter berguna jika Anda ingin menentukan item dalam daftar yang perlu diperbarui saat daftar berubah.

Menyesuaikan RecyclerView

Anda dapat menyesuaikan objek RecyclerView untuk memenuhi kebutuhan spesifik Anda. Class standar ini menyediakan semua fungsi yang diperlukan oleh sebagian besar developer. Biasanya, Anda hanya perlu mendesain tampilan untuk setiap penampung tampilan dan menulis kode untuk memperbarui tampilan tersebut dengan data yang sesuai. Penyesuaian lainnya tidak diperlukan. Namun, jika aplikasi Anda memiliki persyaratan khusus, Anda dapat mengubah perilaku standar ini melalui beberapa cara. Bagian berikut menjelaskan beberapa penyesuaian lain yang umum.

Mengubah tata letak

RecyclerView menggunakan pengelola tata letak untuk menempatkan item tertentu di layar dan menentukan kapan tampilan item yang tidak lagi terlihat oleh pengguna akan digunakan kembali. Untuk menggunakan kembali (atau mendaur ulang) tampilan, pengelola tata letak dapat meminta adaptor untuk mengganti konten tampilan dengan elemen lain dari set data. Daur ulang tampilan semacam ini meningkatkan performa dengan menghindari pembuatan tampilan yang tidak perlu atau melakukan pencarian findViewById() yang menghabiskan banyak resource. Android Support Library menyertakan tiga pengelola tata letak standar, yang masing-masing menawarkan banyak opsi penyesuaian:

Jika semua pengelola tata letak ini tidak sesuai dengan kebutuhan Anda, Anda dapat membuatnya sendiri dengan memperluas class abstrak RecyclerView.LayoutManager.

Menambahkan animasi item

Setiap kali item berubah, RecyclerView akan menggunakan animator untuk mengubah penampilannya. Animator ini adalah objek yang memperluas class RecyclerView.ItemAnimator abstrak. Secara default, RecyclerView menggunakan DefaultItemAnimator untuk menyediakan animasi. Jika ingin memberikan animasi kustom, Anda dapat menentukan objek animator sendiri dengan memperluas RecyclerView.ItemAnimator.

Mengaktifkan pilihan item daftar

Library recyclerview-selection memungkinkan pengguna memilih item dalam daftar RecyclerView melalui input sentuh atau mouse. Anda mempertahankan kontrol atas presentasi visual item yang dipilih. Anda juga dapat mempertahankan kontrol atas kebijakan yang mengendalikan perilaku pemilihan, seperti item yang memenuhi syarat untuk dipilih, dan banyaknya item yang dapat dipilih.

Untuk menambahkan dukungan pemilihan ke instance RecyclerView, ikuti langkah-langkah berikut:

  1. Tentukan jenis kunci pemilihan yang akan digunakan, lalu buat ItemKeyProvider.

    Ada tiga jenis kunci yang dapat Anda gunakan untuk mengidentifikasi item yang dipilih: Parcelable (dan semua subclass seperti Uri), String, dan Long. Untuk informasi mendetail tentang jenis kunci pemilihan, lihat SelectionTracker.Builder.

  2. Implementasikan ItemDetailsLookup.
  3. ItemDetailsLookup mengaktifkan library pemilihan untuk mengakses informasi tentang item RecyclerView dengan memperhitungkan MotionEvent. Secara efektif, ini adalah factory untuk instance ItemDetails yang ditunjang oleh (atau diekstrak dari) instance RecyclerView.ViewHolder.

  4. Perbarui item Views di RecyclerView untuk menunjukkan bahwa pengguna telah memilih atau batal memilih item itu.

    Library pemilihan tidak menyediakan dekorasi visual default untuk item yang dipilih. Anda harus menyediakannya saat mengimplementasikan onBindViewHolder(). Pendekatan yang direkomendasikan adalah sebagai berikut:

  5. Gunakan ActionMode untuk memberikan alat kepada pengguna untuk melakukan tindakan atas pilihan.
  6. Daftarkan SelectionTracker.SelectionObserver untuk menerima pemberitahuan saat pilihan berubah. Saat pilihan dibuat untuk pertama kalinya, jalankan ActionMode untuk menunjukkan ini kepada pengguna, dan menyediakan tindakan untuk pilihan tertentu. Misalnya, Anda dapat menambahkan tombol hapus ke panel ActionMode, dan menghubungkan panah mundur di panel tersebut untuk menghapus pilihan. Setelah pilihan kosong (karena dihapus oleh pengguna), jangan lupa untuk menghentikan mode tindakan.

  7. Lakukan tindakan sekunder apa pun yang diperlukan
  8. Di akhir pipeline pemrosesan peristiwa, library ini dapat menentukan bahwa pengguna mencoba mengaktifkan item dengan mengetuknya, atau mencoba menarik dan melepas sebuah atau serangkaian item yang dipilih. Respons interpretasi ini dengan mendaftarkan pemroses yang sesuai. Untuk informasi selengkapnya, lihat: SelectionTracker.Builder.

  9. Rangkai semuanya dengan SelectionTracker.Builder
  10. Contoh berikut menunjukkan cara menyatukan langkah-langkah di atas menggunakan kunci pemilihan Long:

    Kotlin

        var tracker = SelectionTracker.Builder(
            "my-selection-id",
            recyclerView,
            StableIdKeyProvider(recyclerView),
            MyDetailsLookup(recyclerView),
            StorageStrategy.createLongStorage())
                .withOnItemActivatedListener(myItemActivatedListener)
                .build()
        

    Java

        SelectionTracker tracker = new SelectionTracker.Builder<>(
                "my-selection-id",
                recyclerView,
                new StableIdKeyProvider(recyclerView),
                new MyDetailsLookup(recyclerView),
                StorageStrategy.createLongStorage())
                .withOnItemActivatedListener(myItemActivatedListener)
                .build();
        

    Untuk membuat instance SelectionTracker, aplikasi Anda harus menyediakan RecyclerView.Adapter yang sama dengan yang Anda gunakan untuk menginisialisasi RecyclerView ke SelectionTracker.Builder. Karena alasan ini, Anda mungkin perlu memasukkan instance SelectionTracker, setelah dibuat, ke dalam RecyclerView.Adapter setelah RecyclerView.Adapter dibuat. Jika tidak, Anda tidak akan dapat memeriksa status item yang dipilih dari metode onBindViewHolder().

  11. Sertakan pilihan dalam peristiwa siklus hidup aktivitas.
  12. Agar status pemilihan bertahan di sepanjang peristiwa siklus hidup aktivitas, aplikasi Anda harus memanggil metode onSaveInstanceState() dan onRestoreInstanceState() di pelacak pilihan dari metode onSaveInstanceState() dan onRestoreInstanceState() aktivitas. Aplikasi Anda juga harus memasukkan ID pemilihan unik ke konstruktor SelectionTracker.Builder. ID ini diperlukan karena sebuah aktivitas atau fragmen dapat memiliki lebih dari satu daftar unik yang dapat dipilih, yang semuanya harus dipertahankan dalam status tersimpannya.

    Referensi lainnya

    RecyclerView digunakan dalam aplikasi demo Sunflower.