Sử dụng RecyclerView để hiển thị danh sách có thể cuộn (scrollable list)

1. Trước khi bắt đầu

Khi nghĩ về những ứng dụng mà mình thường dùng trên điện thoại, bạn có thể thấy hầu hết ứng dụng đều có ít nhất một danh sách. Màn hình nhật ký cuộc gọi, ứng dụng danh bạ và ứng dụng mạng xã hội mà bạn yêu thích, tất cả đều hiển thị ít nhất một danh sách dữ liệu. Như ảnh chụp màn hình bên dưới, một số ứng dụng chỉ hiện một danh sách các từ hoặc cụm từ đơn giản. Trong khi đó, những ứng dụng khác sẽ hiện các thành phần phức tạp hơn, chẳng hạn như thẻ chứa văn bản và hình ảnh. Hiển thị danh sách dữ liệu là một trong những tác vụ giao diện người dùng phổ biến nhất trên Android, bất kể nội dung hiển thị là gì.

cf10a913f9db0ee4.png

Android cung cấp thành phần giao diện RecyclerView, cho phép bạn xây dựng ứng dụng với danh sách. RecyclerView được thiết kế rất hiệu quả, có thể sử dụng cho những danh sách lớn, cho phép sử dụng lại hoặc tái chế các thành phần hiển thị (view) đã cuộn ra khỏi màn hình. Khi một phần tử trong danh sách được cuộn khỏi màn hình, RecyclerView sẽ sử dụng lại thành phần hiển thị đó cho phần tử sắp hiện tiếp theo trong danh sách. Điều này có nghĩa rằng phần tử này sẽ chứa nội dung mới cuộn lên màn hình. Tính năng này của RecyclerView giúp tiết kiệm rất nhiều thời gian xử lý, đồng thời giúp cuộn danh sách mượt mà hơn.

Trong chuỗi hiển thị bên dưới, bạn có thể thấy rằng một thành phần hiển thị đã được điền dữ liệu, ABC. Sau khi thành phần hiển thị đó ra khỏi màn hình, RecyclerView sẽ sử dụng lại thành phần đó cho dữ liệu mới, XYZ.

dcf4599789b9c2a1.png

Trong lớp học lập trình này, bạn sẽ tạo ứng dụng Affirmations (Lời tự động viên). Affirmations là một ứng dụng đơn giản hiển thị mười lời tự động viên tích cực dưới dạng văn bản, được hiển thị trong một danh sách cuộn. Sau đó, trong lớp học lập trình tiếp theo, bạn sẽ thực hiện thêm một bước nữa. Trong bước này, bạn sẽ thêm một hình ảnh đầy cảm hứng cho mỗi lời tự động viên và tiếp đó sẽ trau chuốt thêm phần giao diện người dùng của ứng dụng.

Điều kiện tiên quyết

  • Tạo một dự án dựa trên mẫu trong Android Studio.
  • Thêm tài nguyên chuỗi vào một ứng dụng.
  • Định nghĩa bố cục trong XML.
  • Tìm hiểu các lớp và tính kế thừa trong Kotlin (bao gồm các lớp trừu tượng).
  • Kế thừa từ một lớp hiện có và ghi đè các phương thức của lớp đó.
  • Sử dụng tài liệu trên trang developer.android.com dành cho các lớp học thuộc phạm vi khung ứng dụng Android.

Kiến thức bạn sẽ học được

  • Cách sử dụng RecyclerView để hiển thị danh sách dữ liệu.
  • Cách tổ chức mã thành các gói
  • Cách sử dụng trình chuyển đổi (adapter) với RecyclerView để tuỳ chỉnh giao diện của từng phần tử trong danh sách.

Sản phẩm bạn sẽ tạo ra

  • Sử dụng RecyclerView để tạo một ứng dụng hiển thị danh sách các lời tự động viên.

Bạn cần có

  • Máy tính đã cài đặt phiên bản Android Studio 4.1 trở lên.

2. Tạo dự án

Tạo dự án Hoạt động trống (Empty Activity)

Trước khi tạo dự án mới, hãy đảm bảo rằng bạn đang sử dụng Android Studio 4.1 trở lên.

  1. Bắt đầu tạo một dự án Kotlin mới trong Android Studio bằng mẫu Empty Activity (Hoạt động trống).
  2. Nhập tên ứng dụng là Affirmations vào trường Name (Tên), com.example.affirmation vào trường Package name (Tên gói) và chọn API Level 19 (API cấp 19) trong trường Minimum SDK (SDK tối thiểu).
  3. Nhấp vào Finish (Hoàn tất) để tạo dự án.

3. Thiết lập danh sách dữ liệu

Bước tiếp theo trong quá trình tạo ứng dụng Affirmations là thêm tài nguyên ứng dụng. Bạn sẽ thêm đoạn mã sau vào dự án của mình.

  • Tài nguyên chuỗi để hiển thị các lời tự động viên trong ứng dụng.
  • Nguồn dữ liệu để cung cấp danh sách các lời tự động viên cho ứng dụng của bạn.

Thêm các lời tự động viên

  1. Trong cửa sổ Project (Dự án), hãy mở app > res > values > strings.xml. Tệp này hiện có một tài nguyên duy nhất là tên của ứng dụng.
  2. Trong strings.xml, hãy thêm các lời tự động viên dưới dạng tài nguyên chuỗi riêng lẻ. Đặt tên cho các tài nguyên chuỗi này là affirmation1, affirmation2, v.v.

Văn bản chứa các lời tự động viên

I am strong.
I believe in myself.
Each day is a new opportunity to grow and be a better version of myself.
Every challenge in my life is an opportunity to learn from.
I have so much to be grateful for.
Good things are always coming into my life.
New opportunities await me at every turn.
I have the courage to follow my heart.
Things will unfold at precisely the right time.
I will be present in all the moments that this day brings.

Tệp strings.xml hoàn chỉnh sẽ có dạng như sau.

<resources>
    <string name="app_name">Affirmations</string>
    <string name="affirmation1">I am strong.</string>
    <string name="affirmation2">I believe in myself.</string>
    <string name="affirmation3">Each day is a new opportunity to grow and be a better version of myself.</string>
    <string name="affirmation4">Every challenge in my life is an opportunity to learn from.</string>
    <string name="affirmation5">I have so much to be grateful for.</string>
    <string name="affirmation6">Good things are always coming into my life.</string>
    <string name="affirmation7">New opportunities await me at every turn.</string>
    <string name="affirmation8">I have the courage to follow my heart.</string>
    <string name="affirmation9">Things will unfold at precisely the right time.</string>
    <string name="affirmation10">I will be present in all the moments that this day brings.</string>
</resources>

Bây giờ, sau khi thêm tài nguyên chuỗi, bạn có thể tham chiếu các tài nguyên này trong mã của mình dưới dạng R.string.affirmation1 hoặc R.string.affirmation2.

Tạo gói mới

Việc tổ chức mã một cách hợp lý sẽ rất hữu ích cho bạn và các nhà phát triển khác trong quá trình tìm hiểu, bảo trì và mở rộng mã đó. Tương tự như cách tổ chức giấy tờ thành tệp và thư mục, bạn có thể sắp xếp mã thành tệp và gói.

Gói là gì?

  1. Trong Android Studio, trong cửa sổ Project (Dự án) (Android), hãy xem các tệp dự án mới của bạn trong thư mục app > java dành cho ứng dụng Affirmations. Các tệp này sẽ giống như ảnh chụp màn hình bên dưới, bao gồm ba gói, một gói dành cho mã của bạn (com.example.affirmations) và hai gói còn lại dành cho các tệp kiểm thử là (com.example.affirmations (androidTest))com.example.affirmations (test)).

809a0d77a0759dc5.png

  1. Lưu ý rằng các từ trong tên của gói được phân tách bằng dấu chấm.

Bạn có thể khai thác các gói theo hai cách.

  • Tạo nhiều gói cho các phần mã khác nhau. Ví dụ: nhà phát triển thường tách các lớp dùng để làm việc với dữ liệu và các lớp dùng để xây dựng giao diện người dùng thành các gói khác nhau.
  • Sử dụng mã từ các gói khác trong mã của bạn. Để sử dụng lớp từ các gói khác, bạn cần định nghĩa lớp này trong phần phụ thuộc của hệ thống xây dựng. Đây cũng là một phương pháp tiêu chuẩn để nhập (import) các gói này trong mã, nhờ đó bạn có thể sử dụng các tên rút gọn của các gói này (ví dụ: TextView) thay vì các tên đủ điều kiện (ví dụ: android.widget.TextView). Ví dụ: bạn đã sử dụng câu lệnh import cho các lớp như sqrt (import kotlin.math.sqrt) và View (import android.view.View).

Trong ứng dụng Affirmations, ngoài việc nhập các lớp Android và Kotlin, bạn cũng sẽ tổ chức ứng dụng của mình trong nhiều gói. Ngay cả khi không có nhiều lớp trong ứng dụng, bạn cũng nên sử dụng gói để nhóm các lớp theo chức năng.

Đặt tên gói

Bạn có thể đặt tên bất kỳ cho một gói, miễn sao tên đó là duy nhất trên toàn cầu; nghĩa là trước đó chưa có gói nào cùng tên được xuất bản ở bất cứ nơi đâu. Do số lượng gói đã tạo rất lớn và việc có được tên gói ngẫu nhiên và độc đáo là không hề đơn giản nên các lập trình viên thường sử dụng các quy ước để dễ dàng tạo lập và hiểu rõ tên gói hơn.

  • Tên gói thường được đặt theo cấu trúc từ khái quát đến cụ thể, trong đó mỗi thành phần của tên sẽ được viết bằng chữ thường và phân tách nhau bằng dấu chấm. Quan trọng: Dấu chấm chỉ là một phần của tên. Dấu này không thể hiện cho hệ phân cấp mã hoặc chỉ định cấu trúc thư mục!
  • Vì các miền Internet là duy nhất trên toàn cầu nên sử dụng một miền, thường là miền của bạn hoặc miền của doanh nghiệp bạn, làm phần đầu tiên của tên gói là quy ước cần được tuân theo.
  • Bạn có thể chọn tên sao cho mình có thể biết được nội dung bên trong cũng như mối liên hệ giữa các gói.
  • Với các ví dụ về mã như ví dụ này, theo sau com.example thường là tên của ứng dụng.

Dưới đây là một số ví dụ về tên gói được định nghĩa trước và nội dung của các gói này:

  • kotlin.math – Hàm toán học và hằng số.
  • android.widget – Các thành phần hiển thị, chẳng hạn như TextView.

Tạo gói

  1. Trong Android Studio, trong ngăn Project (Dự án), hãy nhấp chuột phải vào app > java > com.example.affirmations rồi chọn New > Package (Mới > Gói).

39f35a81a574b7ee.png

  1. Trong cửa sổ bật lên New Package (Gói mới), hãy chú ý đến tiền tố cho tên gói đề xuất. Phần đầu tiên của tên gói đề xuất là tên của gói mà bạn đã nhấp chuột phải vào. Mặc dù tên gói không tạo nên hệ phân cấp gói, nhưng việc sử dụng lại các phần của tên sẽ cho biết mối quan hệ và cách tổ chức các nội dung trong gói!
  2. Trong cửa sổ bật lên, hãy gắn model vào cuối tên gói được đề xuất. Các nhà phát triển thường sử dụng model làm tên gói cho các lớp mô hình hoá (hoặc đại diện) cho dữ liệu.

3d392f8da53adc6f.png

  1. Nhấn Enter. Thao tác này sẽ tạo một gói mới trong gói com.example.affirmation (gốc). Gói mới này sẽ chứa mọi lớp liên quan đến dữ liệu được định trong ứng dụng của bạn.

Tạo lớp dữ liệu Affirmation

Trong nhiệm vụ này, bạn sẽ tạo một lớp tên là Affirmation. Một thực thể đối tượng của Affirmation sẽ đại diện cho một lời tự động viên và chứa mã nhận dạng tài nguyên của chuỗi chứa lời tự động viên đó.

  1. Nhấp chuột phải vào gói com.example.affirmation.model và chọn New > Kotlin File/Class. (Mới > Tệp/Lớp Kotlin)

a6bc9eb5c382cf9.png

  1. Trong cửa sổ bật lên, hãy chọn Class (Lớp) rồi nhập Affirmation làm tên của lớp đó. Thao tác này sẽ tạo một tệp mới có tên là Affirmation.kt trong gói model.
  2. Thiết lập Affirmation thành lớp dữ liệu bằng cách thêm từ khoá data trước phần định nghĩa lớp. Bạn sẽ thấy lỗi xuất hiện vì phải có ít nhất một thuộc tính được định nghĩa trong một lớp dữ liệu.

Affirmation.kt

package com.example.affirmations.model

data class Affirmation {
}

Khi tạo một thực thể của Affirmation, bạn cần truyền vào mã nhận dạng tài nguyên cho chuỗi chứa lời tự động viên đó. Mã nhận dạng tài nguyên là một số nguyên.

  1. Hãy thêm một tham số kiểu số nguyên val stringResourceId vào hàm khởi tạo của lớp Affirmation. Thao tác này sẽ giúp khắc phục lỗi ở trên.
package com.example.affirmations.model

data class Affirmation(val stringResourceId: Int)

Tạo lớp đóng vai trò là nguồn dữ liệu

Dữ liệu hiển thị trong ứng dụng của bạn có thể đến từ nhiều nguồn khác nhau (ví dụ như trong dự án ứng dụng của bạn hoặc từ một nguồn bên ngoài có yêu cầu kết nối Internet để tải dữ liệu xuống). Do đó, định dạng của dữ liệu có thể không đáp ứng chính xác nhu cầu của bạn. Phần còn lại của ứng dụng không cần quan tâm đến nguồn gốc cũng như định dạng ban đầu của dữ liệu. Bạn có thể và nên đưa phần chuẩn bị dữ liệu này vào trong một lớp Datasource riêng biệt để chuẩn bị dữ liệu cho ứng dụng.

Chuẩn bị dữ liệu là một quan tâm riêng nên hãy đặt lớp Datasource vào một gói data (dữ liệu) riêng.

  1. Trong Android Studio, trong cửa sổ Project (Dự án), hãy nhấp chuột phải vào app > java > com.example.affirmations và chọn New > Package (Mới > Gói).
  2. Nhập data làm phần tên cuối cùng của gói.
  3. Nhấp chuột phải vào gói data rồi chọn New > Kotlin File/Class (Mới > Tệp/Lớp Kotlin).
  4. Nhập tên lớp là Datasource.
  5. Bên trong lớp Datasource, hãy tạo một hàm tên là loadAffirmations().

Hàm loadAffirmations() cần trả về danh sách Affirmations. Bạn thực hiện điều này bằng cách tạo một danh sách và điền vào một thực thể Affirmation cho mỗi chuỗi tài nguyên.

  1. Khai báo kiểu trả về của phương thức loadAffirmations()List<Affirmation>.
  2. Trong thân hàm loadAffirmations(), hãy thêm câu lệnh return.
  3. Sau từ khoá return, hãy gọi listOf<>() để tạo List.
  4. Trong cặp dấu nhọn <>, hãy chỉ định kiểu của các phần tử trong danh sách là Affirmation. Nếu cần, hãy nhập com.example.affirmations.model.Affirmation.
  5. Bên trong dấu ngoặc đơn, hãy tạo một Affirmation, truyền vào mã nhận dạng tài nguyên R.string.affirmation1 như hình bên dưới.
Affirmation(R.string.affirmation1)
  1. Thêm các đối tượng Affirmation còn lại vào danh sách tất cả lời tự động viên, phân tách nhau bằng dấu phẩy. Mã hoàn chỉnh sẽ có dạng như sau.

Datasource.kt

package com.example.affirmations.data

import com.example.affirmations.R
import com.example.affirmations.model.Affirmation

class Datasource {

    fun loadAffirmations(): List<Affirmation> {
        return listOf<Affirmation>(
            Affirmation(R.string.affirmation1),
            Affirmation(R.string.affirmation2),
            Affirmation(R.string.affirmation3),
            Affirmation(R.string.affirmation4),
            Affirmation(R.string.affirmation5),
            Affirmation(R.string.affirmation6),
            Affirmation(R.string.affirmation7),
            Affirmation(R.string.affirmation8),
            Affirmation(R.string.affirmation9),
            Affirmation(R.string.affirmation10)
        )
    }
}

[Không bắt buộc] Hiển thị kích thước của danh sách Lời tự động viên trong TextView

Để kiểm tra xem bạn có thể tạo danh sách các lời tự động viên hay không, bạn có thể gọi loadAffirmations() và hiển thị kích thước của danh sách lời tự động viên được trả về trong TextView đi kèm với mẫu ứng dụng Hoạt động trống (Empty Activity).

  1. Trong layouts/activity_main.xml, hãy cung cấp giá trị id của textview cho TextView đi kèm với mẫu ứng dụng của bạn.
  2. Trong MainActivity, trong phương thức onCreate() nằm sau mã hiện tại, hãy tham chiếu đến textview.
val textView: TextView = findViewById(R.id.textview)
  1. Sau đó, hãy thêm mã để tạo và hiển thị kích thước của danh sách lời tự động viên. Tạo Datasource, gọi hàm loadAffirmations(), lấy kích thước của danh sách trả về, chuyển đổi kích thước này thành một chuỗi và gán giá trị đó vào thuộc tính text của textView.
textView.text = Datasource().loadAffirmations().size.toString()
  1. Chạy ứng dụng. Màn hình sẽ xuất hiện như bên dưới.

b4005973d4a0efc8.png

  1. Xoá mã mà bạn vừa thêm trong MainActivity.

4. Thêm RecyclerView vào ứng dụng của bạn

Trong nhiệm vụ này, bạn sẽ thiết lập một RecyclerView để hiển thị danh sách Affirmations.

Quá trình tạo và sử dụng RecyclerView sẽ liên quan đến một số thành phần. Bạn có thể xem đây như một quá trình phân công lao động. Sơ đồ dưới đây sẽ cung cấp một cái nhìn tổng quan và bạn sẽ tìm hiểu chi tiết hơn về những thành phần này trong quá trình triển khai.

  • phần tử (item) – Một phần tử dữ liệu trong danh sách để hiển thị. Đại diện cho một đối tượng Affirmation trong ứng dụng của bạn.
  • Trình chuyển đổi – Lấy dữ liệu và chuẩn bị dữ liệu này cho RecyclerView hiển thị.
  • ViewHolders – Một tập các thành phần hiển thị được RecyclerView sử dụng và sử dụng lại để hiển thị lời tự động viên.
  • RecyclerView - Các thành phần hiển thị trên màn hình

4e9c18b463f00bf7.png

Thêm RecyclerView vào bố cục

Ứng dụng Affirmations gồm một hoạt động (activity) có tên là MainActivity và tệp bố cục của ứng dụng này có tên là activity_main.xml. Trước tiên, bạn cần thêm RecyclerView vào bố cục của MainActivity.

  1. Mở activity_main.xml (app > res > layout > activity_main.xml)
  2. Nếu bạn chưa sử dụng tệp này, hãy chuyển sang chế độ Phân tách.

7e7c3e8429267dac.png

  1. Xoá TextView.

Bố cục hiện tại sử dụng ConstraintLayout. ConstraintLayout là lựa chọn lý tưởng và linh hoạt khi bạn muốn bố trí nhiều thành phần hiển thị con trong một bố cục. Vì bố cục của bạn chỉ có một thành phần hiển thị con, RecyclerView, bạn có thể chuyển sang một ViewGroup đơn giản hơn gọi là FrameLayout, thường dùng để lưu giữ một thành phần hiển thị con duy nhất.

9e6f235be5fa31a8.png

  1. Trong XML, hãy thay thế ConstraintLayout bằng FrameLayout. Bố cục đã hoàn chỉnh sẽ có dạng như sau.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
</FrameLayout>
  1. Chuyển sang chế độ xem Design (Thiết kế).
  2. Trong Palette (Bảng chế độ xem), hãy chọn Containers (Vùng chứa) và tìm RecyclerView.
  3. Kéo RecyclerView vào bố cục.
  4. Đọc thông tin trong cửa sổ bật lên Add Project Dependency (Thêm phần phụ thuộc dự án) nếu cửa sổ này xuất hiện, sau đó nhấp vào OK. (Nếu cửa sổ bật lên không xuất hiện thì bạn không cần làm gì.)
  5. Hãy đợi Android Studio hoàn tất và RecyclerView sẽ xuất hiện trong bố cục.
  6. Nếu cần, hãy thay đổi thuộc tính layout_widthlayout_height của RecyclerView thành match_parent để RecyclerView có thể lấp đầy toàn bộ màn hình.
  7. Đặt mã nhận dạng tài nguyên của RecyclerView thành recycler_view.

RecyclerView hỗ trợ hiển thị các phần tử theo nhiều cách khác nhau, chẳng hạn như dưới dạng danh sách tuyến tính hoặc dạng lưới. Việc sắp xếp các phần tử sẽ do LayoutManager xử lý. Khung ứng dụng Android sẽ cung cấp các trình quản lý bố cục cho các bố cục thành phần cơ bản. Ứng dụng Affirmations hiển thị các phần tử dưới dạng danh sách theo chiều dọc, nhờ vậy bạn có thể sử dụng LinearLayoutManager.

  1. Chuyển về chế độ xem Code (Mã). Trong mã XML, bên trong phần tử RecyclerView, hãy thiết lập thuộc tính cho trình quản lý bố cục của RecyclerView thành LinearLayoutManager, như minh hoạ bên dưới.
app:layoutManager="LinearLayoutManager"

Để có thể cuộn dọc danh sách các phần tử có kích thước dài hơn màn hình, bạn cần thêm một thanh cuộn dọc.

  1. Bên trong RecyclerView, hãy thêm thuộc tính android:scrollbars và thiết lập giá trị thành vertical.
android:scrollbars="vertical"

Bố cục XML cuối cùng sẽ có dạng như sau:

activity_main.xml

<FrameLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical"
        app:layoutManager="LinearLayoutManager" />

</FrameLayout>
  1. Chạy ứng dụng của bạn.

Đảm bảo không gặp bất kỳ vấn đề nào trong quá trình biên dịch và chạy ứng dụng của bạn. Tuy nhiên, bạn chỉ thấy ứng dụng hiển thị nền trắng do thiếu một đoạn mã quan trọng. Hiện tại, bạn đã có nguồn dữ liệu và đã thêm RecyclerView vào bố cục, nhưng RecyclerView không có thông tin về cách hiển thị các đối tượng Affirmation.

Triển khai Trình chuyển đổi cho RecyclerView

Ứng dụng của bạn cần biết cách để lấy dữ liệu từ Datasource và định dạng dữ liệu này để mỗi Affirmation đều được hiển thị dưới dạng một phần tử trong RecyclerView.

Trình chuyển đổi là một mẫu thiết kế cho phép điều chỉnh dữ liệu để RecyclerView có thể dùng được. Trong trường hợp này, bạn cần một trình chuyển đổi để lấy thực thể của Affirmation từ danh sách trả về của hàm loadAffirmations(). Sau đó, chuyển thực thể này thành một thành phần hiển thị phần tử trong danh sách (list item view). Nhờ đó, thành phần này mới có thể hiển thị trong RecyclerView.

Khi chạy ứng dụng, RecyclerView sẽ sử dụng trình chuyển đổi này để tìm cách hiện dữ liệu trên màn hình. RecyclerView yêu cầu trình chuyển đổi tạo một thành phần hiển thị phần tử trong danh sách mới (new list item view) cho phần tử dữ liệu đầu tiên trong danh sách của bạn. Khi đã tạo thành phần hiển thị này, RecyclerView sẽ yêu cầu trình chuyển đổi cung cấp dữ liệu để vẽ phần tử này. Quá trình này lặp lại cho đến khi RecyclerView không cần thêm thành phần hiển thị nào nữa để lấp đầy màn hình. Nếu màn hình chỉ cho phép hiện cùng lúc 3 thành phần hiển thị phần tử trong danh sách, thì RecyclerView chỉ yêu cầu trình chuyển đổi chuẩn bị 3 thành phần hiển thị đó (thay vì chuẩn bị tất cả 10 thành phần hiển thị).

Trong bước này, bạn sẽ tạo một trình chuyển đổi có khả năng điều chỉnh thực thể của đối tượng Affirmation để có thể hiển thị thực thể đó trong RecyclerView.

Tạo Trình chuyển đổi

Trình chuyển đổi có nhiều thành phần khác nhau và bạn sẽ viết khá nhiều mã phức tạp hơn so với những gì bạn đã viết từ đầu khoá học này. Bạn đừng lo lắng nếu chưa hiểu đầy đủ các chi tiết vào lúc đầu. Sau khi hoàn thành toàn bộ ứng dụng này bằng RecyclerView, bạn sẽ hiểu rõ hơn về cách thức khớp nối lẫn nhau giữa các thành phần này. Bạn cũng có thể sử dụng lại mã này làm cơ sở để tạo các ứng dụng trong tương lai với RecyclerView.

Tạo bố cục cho các phần tử (item)

Mỗi phần tử trong RecyclerView có bố cục riêng được định nghĩa trong một tệp bố cục riêng. Vì bạn chỉ muốn hiển thị một chuỗi nên có thể sử dụng TextView cho bố cục thành phần (item layout) của mình.

  1. Trong res > layout, hãy tạo một File (Tệp) trống có tên là list_item.xml.
  2. Mở list_item.xml ở chế độ xem Code (Mã).
  3. Thêm một TextView với id item_title.
  4. Thêm wrap_content cho layout_widthlayout_height, như minh hoạ trong mã bên dưới.

Lưu ý rằng bạn không cần một ViewGroup xung quanh bố cục của mình. Lý do là bố cục thành phần của danh sách này sẽ được tăng cường sau này và được thêm vào như một thành phần con của RecyclerView.

list_item.xml

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

Ngoài ra, có thể bạn đã sử dụng chức năng File > New > Layout Resource File (Tệp > Mới > Tệp tài nguyên bố cục), trong đó File name (Tên tệp) là list_item.xmlRoot element (Phần tử gốc) là TextView. Tiếp đó, hãy cập nhật mã đã tạo để khớp với mã ở trên.

dbb34ca516c804c6.png

Tạo lớp ItemAdapter

  1. Trong ngăn Project (Dự án) trong Android Studio, hãy nhấp chuột phải vào app > java > com.example.affirmations rồi chọn New > Package (Mới > Gói).
  2. Nhập adapter làm phần tên cuối cùng của gói.
  3. Nhấp chuột phải vào gói adapter rồi chọn New > Kotlin File/Class (Mới > Tệp/Lớp Kotlin).
  4. Nhập tên lớp là ItemAdapter, hoàn tất và tệp ItemAdapter.kt sẽ mở ra.

Bạn cần thêm một tham số vào hàm khởi tạo của ItemAdapter. Nhờ đó, bạn có thể truyền danh sách lời tự động viên vào trình chuyển đổi.

  1. Thêm một tham số vào hàm khởi tạo ItemAdapter. Đó là một val có tên là dataset thuộc kiểu List<Affirmation>. Nhập Affirmation, nếu cần thiết.
  2. Do dataset chỉ được sử dụng trong lớp này, hãy chỉ định biến này thành private.

ItemAdapter.kt

import com.example.affirmations.model.Affirmation

class ItemAdapter(private val dataset: List<Affirmation>) {

}

ItemAdapter cần thông tin về cách phân giải (resolve) tài nguyên chuỗi. Thông tin này và những thông tin khác về ứng dụng sẽ được lưu trữ trong một thực thể đối tượng Context mà bạn có thể truyền vào một thực thể của ItemAdapter.

  1. Thêm một tham số vào hàm khởi tạo ItemAdapter. Đó là một val có tên là context thuộc kiểu Context. Đặt tham số này làm tham số đầu tiên trong hàm khởi tạo.
class ItemAdapter(private val context: Context, private val dataset: List<Affirmation>) {

}

Tạo ViewHolder

RecyclerView không tương tác trực tiếp với thành phần hiển thị phần tử (item view) nhưng lại tương tác với ViewHolders. ViewHolder đại diện cho một thành phần hiển thị phần tử trong danh sách trong RecyclerView và có thể được sử dụng lại khi có thể. Thực thể của ViewHolder lưu giữ các tham chiếu đến từng thành phần hiển thị trong bố cục thành phần của danh sách (do đó có tên là "trình lưu giữ thành phần hiển thị"). Bằng cách này, bạn có thể dễ dàng cập nhật dữ liệu mới cho thành phần hiển thị phần tử trong danh sách. Trình lưu giữ thành phần hiển thị (view holder) cũng bổ sung thông tin mà RecyclerView sử dụng để di chuyển các thành phần hiển thị xung quanh màn hình một cách hiệu quả.

  1. Bên trong lớp ItemAdapter, trước dấu ngoặc nhọn đóng cho ItemAdapter, hãy tạo một lớp ItemViewHolder.
class ItemAdapter(private val context: Context, private val dataset: List<Affirmation>) {

    class ItemViewHolder()
}
  • Quá trình định nghĩa một lớp bên trong một lớp khác được gọi là quá trình tạo lớp lồng nhau (nested class).
  • ItemViewHolder chỉ được ItemAdapter sử dụng, việc tạo lớp này bên trong ItemAdapter cho thấy mối quan hệ này. Điều này không bắt buộc nhưng sẽ giúp các nhà phát triển khác hiểu được cấu trúc chương trình của bạn.
  1. Thêm tham số private val view thuộc kiểu View vào hàm khởi tạo của lớp ItemViewHolder.
  2. Thiết lập ItemViewHolder làm lớp con của RecyclerView.ViewHolder và truyền tham số view vào hàm khởi tạo của lớp cha.
  3. Bên trong ItemViewHolder, định nghĩa thuộc tính val textView có kiểu TextView. Gán thuộc tính này bằng thành phần hiển thị có mã nhận dạng item_title đã định nghĩa trong list_item.xml.
class ItemAdapter(private val context: Context, private val dataset: List<Affirmation>) {

    class ItemViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
        val textView: TextView = view.findViewById(R.id.item_title)
    }
}

Ghi đè phương thức của trình chuyển đổi

  1. Thêm mã để mở rộng lớp ItemAdapter từ lớp trừu tượng RecyclerView.Adapter. Chỉ định ItemAdapter.ItemViewHolder làm kiểu trình lưu giữ thành phần hiển thị (view holder) trong cặp dấu nhọn (<>).
class ItemAdapter(
    private val context: Context,
    private val dataset: List<Affirmation>
) : RecyclerView.Adapter<ItemAdapter.ItemViewHolder>() {

    class ItemViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
        val textView: TextView = view.findViewById(R.id.item_title)
    }
}

Bạn sẽ thấy lỗi xuất hiện vì bạn cần triển khai một số phương thức trừu tượng của RecyclerView.Adapter.

  1. Đặt con trỏ lên ItemAdapter rồi nhấn Command+I (Control+I trên Windows). Thao tác này sẽ hiển thị danh sách các phương thức bạn cần triển khai: getItemCount(), onCreateViewHolder()onBindViewHolder().

7a8a383a8633094b.png

  1. Chọn cả ba phương thức này bằng cách sử dụng Shift+nhấp chuột và nhấp vào OK.

Thao tác này sẽ tạo các đoạn mã sơ khai gồm các tham số chính xác cho 3 phương thức như bên dưới.

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
    TODO("Not yet implemented")
}

override fun getItemCount(): Int {
    TODO("Not yet implemented")
}

override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
    TODO("Not yet implemented")
}

Bạn sẽ không thấy xuất hiện lỗi nào nữa. Tiếp theo, bạn cần triển khai các phương thức này để thực hiện chính xác các yêu cầu của ứng dụng.

Triển khai phương thức getItemCount()

Phương thức getItemCount() cần trả về kích thước của tập dữ liệu. Dữ liệu của ứng dụng nằm trong thuộc tính dataset bạn đang truyền vào hàm khởi tạo ItemAdapter. Bạn có thể lấy kích thước của tập dữ liệu bằng thuộc tính size.

  1. Thay thế getItemCount() bằng mã sau:
override fun getItemCount() = dataset.size

Dưới đây là cách viết ngắn gọn hơn:

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

Triển khai phương thức onCreateViewHolder()

Trình quản lý bố cục gọi phương thức onCreateViewHolder() để tạo trình lưu giữ thành phần hiển thị mới choRecyclerView (nếu hiện tại không có trình lưu giữ thành phần hiển thị nào có thể sử dụng lại được). Hãy nhớ rằng trình lưu giữ thành phần hiển thị (view holder) đại diện cho một thành phần hiển thị phần tử trong danh sách (list item view).

Phương thức onCreateViewHolder() có hai tham số và trả về một ViewHolder mới.

  • Tham số parent, là nhóm thành phần hiển thị (view group) chứa thành phần hiển thị phần tử trong danh sách mới (phần tử con). Thành phần mẹ ở đây là RecyclerView.
  • Tham số viewType trở nên quan trọng khi có nhiều kiểu thành phần hiển thị phần tử (item view types) trong cùng RecyclerView. Nếu có các bố cục thành phần danh sách (list item layout) khác nhau hiển thị trong RecyclerView thì sẽ có các kiểu thành phần hiển thị phần tử khác nhau. Bạn chỉ có thể tái sử dụng các thành phần hiển thị có cùng kiểu thành phần hiển thị phần tử. Trong trường hợp của bạn, chỉ có một bố cục thành phần danh sách và một kiểu thành phần hiển thị phần tử nên bạn không cần lo lắng về tham số này.
  1. Trong phương thức onCreateViewHolder(), lấy một thực thể của LayoutInflater từ ngữ cảnh đã cung cấp (context của parent). Trình tăng cường bố cục (layout inflater) biết cách để tăng cường bố cục XML thành một hệ phân cấp các đối tượng của thành phần hiển thị.
val adapterLayout = LayoutInflater.from(parent.context)
  1. Sau khi đã có thực thể của đối tượng LayoutInflater, hãy thêm một dấu chấm, theo sau là một lệnh gọi phương thức khác để tăng cường thành phần hiển thị phần tử trong danh sách thực tế. Truyền vào mã nhận dạng tài nguyên bố cục XML R.layout.list_item và nhóm thành phần hiển thị parent. Đối số boolean thứ ba là attachToRoot. Đối số này cần mang giá trị false bởi vì RecyclerView sẽ thêm phần tử này vào hệ phân cấp thành phần hiển thị vào thời điểm thích hợp.
val adapterLayout = LayoutInflater.from(parent.context)
       .inflate(R.layout.list_item, parent, false)

Bây giờ, adapterLayout lưu giữ một tham chiếu đến thành phần hiển thị phần tử trong danh sách (từ đó chúng ta có thể tìm thấy

các thành phần hiển thị con như TextView sau này).

  1. Trong onCreateViewHolder(), hãy trả về một thực thể ItemViewHolder mới có thành phần hiển thị gốc là adapterLayout.
return ItemViewHolder(adapterLayout)

Dưới đây là toàn bộ mã cho onCreateViewHolder() cho đến thời điểm này.

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
    // create a new view
    val adapterLayout = LayoutInflater.from(parent.context)
        .inflate(R.layout.list_item, parent, false)

    return ItemViewHolder(adapterLayout)
}

Triển khai phương thức onBindViewHolder()

Phương thức cuối cùng bạn cần ghi đè là onBindViewHolder(). Trình quản lý bố cục sẽ gọi phương thức này để thay thế nội dung của thành phần hiển thị phần tử trong danh sách.

Phương thức onBindViewHolder() có hai tham số, trong đó tham số ItemViewHolder được tạo trước đó bằng phương thức onCreateViewHolder() và phương thức int đại diện cho phần tử hiện tại position trong danh sách. Trong phương thức này, bạn sẽ tìm thấy đối tượng Affirmation phù hợp từ tập dữ liệu dựa trên vị trí.

  1. Bên trong onBindViewHolder(), tạo một val item và lấy phần tử này tại position cho trước trong dataset.
val item = dataset[position]

Cuối cùng, bạn cần cập nhật tất cả thành phần hiển thị được trình lưu giữ chế độ xem tham chiếu đến để phản ánh đúng dữ liệu của phần tử này. Trong trường hợp này, chỉ có một thành phần hiển thị: TextView trong ItemViewHolder. Thiết lập văn bản của TextView để hiển thị chuỗi Affirmation cho phần tử này.

  1. Với một thực thể của đối tượng Affirmation, bạn có thể tìm thấy mã nhận dạng tài nguyên chuỗi tương ứng bằng cách gọi item.stringResourceId. Tuy nhiên, đây là một số nguyên và bạn cần tìm ánh xạ tới giá trị chuỗi thực.

Trong khung ứng dụng Android, bạn có thể gọi phương thức getString() và truyền vào mã nhận dạng tài nguyên chuỗi. Giá trị trả về sẽ là giá trị chuỗi liên kết với mã tài nguyên đó. getString() là một phương thức trong lớp Resources và bạn có thể lấy thực thể của lớp Resources thông qua context.

Điều đó có nghĩa rằng bạn có thể gọi context.resources.getString() và truyền vào một mã nhận dạng tài nguyên chuỗi. Chuỗi kết quả trả về sẽ được gán cho thuộc tính text của textView trong holder ItemViewHolder. Tóm lại, dòng mã này sẽ cập nhật trình lưu giữ thành phần hiển thị để hiển thị lời tự động viên.

holder.textView.text = context.resources.getString(item.stringResourceId)

Phương thức onBindViewHolder() hoàn thiện sẽ có dạng như sau.

override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
    val item = dataset[position]
    holder.textView.text =  context.resources.getString(item.stringResourceId)
}

Sau đây là mã hoàn thiện cho trình chuyển đổi.

ItemAdapter.kt

package com.example.affirmations.adapter

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.example.affirmations.R
import com.example.affirmations.model.Affirmation

/**
 * Adapter for the [RecyclerView] in [MainActivity]. Displays [Affirmation] data object.
 */
class ItemAdapter(
    private val context: Context,
    private val dataset: List<Affirmation>
) : RecyclerView.Adapter<ItemAdapter.ItemViewHolder>() {

    // 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 an Affirmation object.
    class ItemViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
        val textView: TextView = view.findViewById(R.id.item_title)
    }

    /**
     * Create new views (invoked by the layout manager)
     */
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
        // create a new view
        val adapterLayout = LayoutInflater.from(parent.context)
            .inflate(R.layout.list_item, parent, false)

        return ItemViewHolder(adapterLayout)
    }

    /**
     * Replace the contents of a view (invoked by the layout manager)
     */
    override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
        val item = dataset[position]
        holder.textView.text = context.resources.getString(item.stringResourceId)
    }

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

Đến thời điểm hiện tại, bạn đã triển khai ItemAdapter, bạn cần yêu cầu RecyclerView sử dụng trình chuyển đổi này.

Chỉnh sửa MainActivity để sử dụng RecyclerView

Để hoàn thành công đoạn cuối cùng, bạn cần sử dụng lớp DatasourceItemAdapter để tạo và hiển thị các phần tử trong RecyclerView. Bạn thực hiện thao tác này trong MainActivity.

  1. Mở MainActivity.kt.
  2. Trong MainActivity,, chuyển đến phương thức onCreate(). Chèn mã mới như được mô tả trong các bước tiếp theo sau khi gọi đến setContentView(R.layout.activity_main).
  3. Tạo một thực thể của Datasource và gọi phương thức loadAffirmations() trên thực thể đó. Lưu danh sách lời tự động viên được trả về trong một biến val có tên myDataset.
val myDataset = Datasource().loadAffirmations()
  1. Tạo biến có tên recyclerView và sử dụng phương thức findViewById() để tìm tham chiếu đến RecyclerView trong bố cục.
val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
  1. Để yêu cầu recyclerView sử dụng lớp ItemAdapter đã tạo, hãy tạo một thực thể mới của ItemAdapter. ItemAdapter yêu cầu hai tham số: ngữ cảnh (this) của hoạt động này và lời tự động viên trong myDataset.
  2. Gán đối tượng ItemAdapter cho thuộc tính adapter của recyclerView.
recyclerView.adapter = ItemAdapter(this, myDataset)
  1. Vì kích thước bố cục của RecyclerView là cố định trong bố cục hoạt động, bạn có thể đặt tham số setHasFixedSize của RecyclerView thành true. Tuỳ chọn thiết lập này chỉ cần thiết khi muốn cải thiện hiệu quả hoạt động. Hãy sử dụng tuỳ chọn này nếu bạn biết rằng việc thay đổi nội dung sẽ không ảnh hưởng đến kích thước bố cục của RecyclerView.
recyclerView.setHasFixedSize(true)
  1. Khi hoàn thành, mã cho MainActivity sẽ tương tự như sau.

MainActivity.kt

package com.example.affirmations

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.RecyclerView
import com.example.affirmations.adapter.ItemAdapter
import com.example.affirmations.data.Datasource

class MainActivity : AppCompatActivity() {

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

        // Initialize data.
        val myDataset = Datasource().loadAffirmations()

        val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
        recyclerView.adapter = ItemAdapter(this, myDataset)

        // 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)
    }
}
  1. Chạy ứng dụng. Bạn sẽ thấy danh sách các lời tự động viên hiển thị trên màn hình.

427c10d4f29d769d.png

Xin chúc mừng! Bạn vừa tạo ứng dụng hiển thị danh sách dữ liệu với RecyclerView và một trình chuyển đổi tuỳ chỉnh. Hãy dành thời gian để xem mã bạn đã tạo và hiểu được cách thức các thành phần tương tác với nhau như thế nào.

Ứng dụng này có tất cả phần bắt buộc để hiển thị lời tự động viên của bạn nhưng vẫn chưa sẵn sàng để phát hành chính thức. Vẫn còn một số điểm cần cải thiện đối với giao diện người dùng. Trong lớp học lập trình tiếp theo, bạn sẽ nâng cấp mã của mình, tìm hiểu cách thêm hình ảnh vào ứng dụng và trau chuốt thêm cho phần giao diện người dùng.

5. Mã giải pháp

Mã giải pháp cho lớp học lập trình này nằm trong dự án và mô-đun được hiển thị bên dưới. Lưu ý rằng một số tệp Kotlin nằm trong các gói khác nhau và được chỉ rõ trong lệnh package ở đầu tệp.

res/values/strings.xml

<resources>
    <string name="app_name">Affirmations</string>
    <string name="affirmation1">I am strong.</string>
    <string name="affirmation2">I believe in myself.</string>
    <string name="affirmation3">Each day is a new opportunity to grow and be a better version of myself.</string>
    <string name="affirmation4">Every challenge in my life is an opportunity to learn from.</string>
    <string name="affirmation5">I have so much to be grateful for.</string>
    <string name="affirmation6">Good things are always coming into my life.</string>
    <string name="affirmation7">New opportunities await me at every turn.</string>
    <string name="affirmation8">I have the courage to follow my heart.</string>
    <string name="affirmation9">Things will unfold at precisely the right time.</string>
    <string name="affirmation10">I will be present in all the moments that this day brings.</string>
</resources>

affirmations/data/Datasource.kt

package com.example.affirmations.data

import com.example.affirmations.R
import com.example.affirmations.model.Affirmation

class Datasource {

    fun loadAffirmations(): List<Affirmation> {
        return listOf<Affirmation>(
            Affirmation(R.string.affirmation1),
            Affirmation(R.string.affirmation2),
            Affirmation(R.string.affirmation3),
            Affirmation(R.string.affirmation4),
            Affirmation(R.string.affirmation5),
            Affirmation(R.string.affirmation6),
            Affirmation(R.string.affirmation7),
            Affirmation(R.string.affirmation8),
            Affirmation(R.string.affirmation9),
            Affirmation(R.string.affirmation10)
        )
    }
}

affirmations/model/Affirmation.kt

package com.example.affirmations.model

data class Affirmation(val stringResourceId: Int)

affirmations/MainActivty.kt

package com.example.affirmations

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.RecyclerView
import com.example.affirmations.adapter.ItemAdapter
import com.example.affirmations.data.Datasource

class MainActivity : AppCompatActivity() {

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

        // Initialize data.
        val myDataset = Datasource().loadAffirmations()

        val recyclerView = findViewById<RecyclerView>(R.id.recycler_view)
        recyclerView.adapter = ItemAdapter(this, myDataset)

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

affirmations/adapter/ItemAdapter.kt

package com.example.affirmations.adapter

import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.example.affirmations.R
import com.example.affirmations.model.Affirmation

/**
 * Adapter for the [RecyclerView] in [MainActivity]. Displays [Affirmation] data object.
 */
class ItemAdapter(
    private val context: Context,
    private val dataset: List<Affirmation>
) : RecyclerView.Adapter<ItemAdapter.ItemViewHolder>() {

    // 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 an Affirmation object.
    class ItemViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
        val textView: TextView = view.findViewById(R.id.item_title)
    }

    /**
     * Create new views (invoked by the layout manager)
     */
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder {
        // create a new view
        val adapterLayout = LayoutInflater.from(parent.context)
            .inflate(R.layout.list_item, parent, false)

        return ItemViewHolder(adapterLayout)
    }

    /**
     * Replace the contents of a view (invoked by the layout manager)
     */
    override fun onBindViewHolder(holder: ItemViewHolder, position: Int) {
        val item = dataset[position]
        holder.textView.text = context.resources.getString(item.stringResourceId)
    }

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

src/main/res/layout/activty_main.xml

<FrameLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical"
        app:layoutManager="LinearLayoutManager" />

</FrameLayout>

src/main/res/layout/list_item.xml

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

6. Tóm tắt

  • Tiện ích RecyclerView giúp bạn hiển thị danh sách dữ liệu.
  • RecyclerView sử dụng một mẫu của trình chuyển đổi để điều chỉnh và hiển thị dữ liệu.
  • ViewHolder tạo và lưu giữ các thành phần hiển thị cho RecyclerView.
  • RecyclerView đi kèm với LayoutManagers được tích hợp sẵn. RecyclerView uỷ quyền cách bố trí các phần tử cho LayoutManagers.

Để triển khai trình chuyển đổi, bạn hãy thực hiện các bước sau:

  • Tạo một lớp mới cho trình chuyển đổi, ví dụ: ItemAdapter.
  • Tạo một lớp ViewHolder tuỳ chỉnh đại diện cho một thành phần hiển thị phần tử trong danh sách. Mở rộng lớp này từ lớp RecyclerView.ViewHolder.
  • Chỉnh sửa lớp ItemAdapter để mở rộng lớp này từ lớp RecyclerViewAdapter với lớp ViewHolder tuỳ chỉnh.
  • Triển khai các phương thức này trong trình chuyển đổi: getItemsCount(), onCreateViewHolder()onBindViewHolder().

7. Tìm hiểu thêm