Android Kotlin Fundamentals 07.5: Tiêu đề trong RecyclerView

Lớp học lập trình này nằm trong khóa học về Khái niệm cơ bản về Android Kotlin. Bạn sẽ nhận được nhiều giá trị nhất từ khóa học này nếu bạn làm việc qua các lớp học lập trình theo trình tự. Tất cả các lớp học lập trình trong khóa học đều có trên trang đích của các lớp học lập trình cơ bản về Android Kotlin.

Giới thiệu

Trong lớp học lập trình này, bạn sẽ tìm hiểu cách thêm tiêu đề kéo dài theo chiều rộng của danh sách hiển thị trong RecyclerView. Bạn tạo ứng dụng theo dõi giấc ngủ từ các lớp học lập trình trước đó.

Kiến thức bạn cần có

  • Cách xây dựng giao diện người dùng cơ bản bằng cách sử dụng hoạt động, mảnh và chế độ xem.
  • Cách di chuyển giữa các mảnh và cách sử dụng safeArgs để chuyển dữ liệu giữa các mảnh.
  • Xem các mô hình, xem thông tin về nhà máy, phép biến đổi, LiveData và các đối tượng tiếp nhận dữ liệu của các mô hình đó.
  • Cách tạo cơ sở dữ liệu Room, tạo DAO và xác định các thực thể.
  • Cách sử dụng coroutine để tương tác với cơ sở dữ liệu và các tác vụ chạy trong thời gian dài khác.
  • Cách triển khai RecyclerView cơ bản bằng bố cục Adapter, ViewHolder và mục.
  • Cách triển khai liên kết dữ liệu cho RecyclerView.
  • Cách tạo và sử dụng bộ chuyển đổi liên kết để chuyển đổi dữ liệu.
  • Cách sử dụng GridLayoutManager.
  • Cách ghi lại và xử lý các lượt nhấp vào mục trong RecyclerView.

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

  • Cách sử dụng nhiều ViewHolder với RecyclerView để thêm mục có bố cục khác. Cụ thể là cách sử dụng ViewHolder thứ hai để thêm tiêu đề phía trên các mục hiển thị trong RecyclerView.

Bạn sẽ thực hiện

  • Xây dựng dựa trên ứng dụng TrackMySleepChất lượng từ lớp học lập trình trước đó trong loạt bài này.
  • Thêm một tiêu đề kéo dài theo chiều rộng của màn hình phía trên các đêm ngủ được hiển thị trong RecyclerView.

Ứng dụng theo dõi giấc ngủ mà bạn bắt đầu có 3 màn hình, được biểu thị bằng các mảnh, như minh họa trong hình bên dưới.

Màn hình đầu tiên (hiển thị ở bên trái) có các nút để bắt đầu và dừng theo dõi. Màn hình hiển thị một số dữ liệu giấc ngủ của người dùng. Nút Xóa xóa vĩnh viễn tất cả dữ liệu mà ứng dụng đã thu thập cho người dùng. Màn hình thứ hai, hiển thị ở giữa, cho thấy một điểm xếp hạng chất lượng giấc ngủ. Màn hình thứ ba là chế độ xem chi tiết sẽ mở ra khi người dùng nhấn vào một mục trong lưới.

Ứng dụng này dùng một cấu trúc đơn giản có bộ điều khiển giao diện người dùng, mô hình chế độ xem, LiveData và cơ sở dữ liệu Room để duy trì dữ liệu về giấc ngủ.

Trong lớp học lập trình này, bạn thêm một tiêu đề vào lưới của các mục hiển thị. Màn hình chính cuối cùng sẽ như sau:

Lớp học mã này hướng dẫn nguyên tắc chung về việc đưa các mục sử dụng bố cục khác nhau vào RecyclerView. Một ví dụ phổ biến là có tiêu đề trong danh sách hoặc lưới của bạn. Danh sách có thể có một tiêu đề để mô tả nội dung mục. Một danh sách cũng có thể có nhiều tiêu đề để nhóm và tách các mục trong một danh sách.

RecyclerView không biết gì về dữ liệu của bạn hoặc loại bố cục của từng mục. LayoutManager sắp xếp các mục trên màn hình, nhưng bộ chuyển đổi điều chỉnh dữ liệu sẽ hiển thị và chuyển các lớp lưu giữ chế độ xem đến RecyclerView. Vì vậy, bạn sẽ thêm mã để tạo tiêu đề trong bộ chuyển đổi.

Hai cách thêm tiêu đề

Trong RecyclerView, mỗi mục trong danh sách tương ứng với một số chỉ mục bắt đầu từ 0. Ví dụ:

[Dữ liệu thực tế] –> [Lượt xem bộ chuyển đổi]

[0: Sleepnight] -> [0: SleepNight]

[1: SleepNight] -> [1: SleepNight]

[2: Sleepnight] -> [2: SleepNight]

Một cách để thêm tiêu đề vào danh sách là sửa đổi bộ chuyển đổi để sử dụng ViewHolder khác bằng cách kiểm tra chỉ mục nơi tiêu đề cần hiển thị. Adapter sẽ chịu trách nhiệm theo dõi tiêu đề. Ví dụ: để hiển thị tiêu đề ở đầu bảng, bạn cần phải trả về ViewHolder khác cho tiêu đề trong khi bố trí mục không được lập chỉ mục. Sau đó, tất cả các mục khác sẽ được liên kết với phần bù tiêu đề, như minh họa bên dưới.

[Dữ liệu thực tế] –> [Lượt xem bộ chuyển đổi]

[0: Tiêu đề]

[0: SleepNight] -> [1: Sleepnight]

[1: SleepNight] -> [2: SleepNight]

[2: SleepNight] -> [3: SleepNight.{/1}

Một cách khác để thêm tiêu đề là sửa đổi tập dữ liệu sao lưu cho lưới dữ liệu của bạn. Vì tất cả dữ liệu cần được hiển thị đều được lưu trữ trong danh sách, bạn có thể sửa đổi danh sách để bao gồm các mục đại diện cho một tiêu đề. Điều này hơi đơn giản hơn một chút, nhưng bạn phải suy nghĩ về cách bạn thiết kế đối tượng để có thể kết hợp nhiều loại mục vào một danh sách duy nhất. Khi được triển khai theo cách này, bộ chuyển đổi sẽ hiển thị các mục được chuyển đến. Vì vậy, mục ở vị trí 0 là tiêu đề và mục ở vị trí 1 là một SleepNight, ánh xạ trực tiếp đến nội dung trên màn hình.

[Dữ liệu thực tế] –> [Lượt xem bộ chuyển đổi]

[0: Tiêu đề] -> [0: Tiêu đề]

[1: SleepNight] -> [1: SleepNight]

[2: Sleepnight] -> [2: SleepNight]

[3: SleepNight] -> [3: SleepNight]

Mỗi phương pháp đều có lợi ích và hạn chế. Việc thay đổi tập dữ liệu không ảnh hưởng nhiều đến phần còn lại của mã bộ chuyển đổi và bạn có thể thêm logic tiêu đề bằng cách thao tác danh sách dữ liệu. Ngược lại, bằng cách sử dụng một ViewHolder khác bằng cách kiểm tra chỉ mục cho các tiêu đề, bạn có thể linh hoạt hơn khi bố cục tiêu đề. Bộ chuyển đổi cũng cho phép bộ chuyển đổi xử lý cách điều chỉnh dữ liệu cho phù hợp với chế độ xem mà không cần sửa đổi dữ liệu sao lưu.

Trong lớp học lập trình này, bạn cập nhật RecyclerView để hiển thị tiêu đề ở đầu danh sách. Trong trường hợp này, ứng dụng sẽ dùng một ViewHolder cho tiêu đề khác với mục dữ liệu. Ứng dụng sẽ kiểm tra chỉ mục của danh sách để xác định ViewHolder nên sử dụng.

Bước 1: Tạo một lớp DataItem

Để trừu tượng hóa loại mục và cho phép bộ chuyển đổi chỉ xử lý "items", bạn có thể tạo một lớp lưu giữ dữ liệu đại diện cho một SleepNight hoặc một Header. Tập dữ liệu của bạn sẽ là một danh sách các mục chứa dữ liệu.

Bạn có thể tải ứng dụng dành cho người mới bắt đầu từ GitHub hoặc tiếp tục sử dụng ứng dụng SleepTracker mà bạn đã xây dựng trong lớp học lập trình trước đó.

  1. Tải mã RecyclerViewHeaders-Starter xuống từ GitHub. Thư mục RecyclerViewHeaders-Starter chứa phiên bản dành cho người mới bắt đầu của ứng dụng SleepTracker trong lớp học lập trình này. Bạn cũng có thể tiếp tục dùng ứng dụng đã hoàn tất trong lớp học lập trình trước đó nếu muốn.
  2. Mở SleepnightAdapter.kt.
  3. Bên dưới lớp SleepNightListener, ở cấp cao nhất, hãy xác định lớp sealed có tên là DataItem đại diện cho một mục dữ liệu.

    Lớp sealed xác định một loại đã đóng, nghĩa là tất cả các lớp con của DataItem phải được xác định trong tệp này. Kết quả là trình biên dịch biết số lớp con. Phần khác của mã không thể xác định một loại DataItem mới có thể làm hỏng bộ chuyển đổi.
sealed class DataItem {

 }
  1. Bên trong phần nội dung của lớp DataItem, hãy xác định hai lớp đại diện cho các loại mục dữ liệu. Đầu tiên là SleepNightItem, là một trình bao bọc xung quanh SleepNight, vì vậy, giá trị này chỉ có một giá trị có tên là sleepNight. Để lớp này thuộc lớp bị đóng, hãy yêu cầu mở rộng DataItem.
data class SleepNightItem(val sleepNight: SleepNight): DataItem()
  1. Lớp thứ hai là Header, để đại diện cho tiêu đề. Vì một tiêu đề không có dữ liệu thực tế nên bạn có thể khai báo tiêu đề đó là object. Điều đó có nghĩa là sẽ chỉ có một phiên bản của Header. Xin nhắc lại, yêu cầu mở rộng DataItem.
object Header: DataItem()
  1. Bên trong DataItem, ở cấp lớp, hãy xác định thuộc tính abstract Long có tên id. Khi bộ chuyển đổi dùng DiffUtil để xác định xem một mặt hàng có thay đổi hay không và DiffItemCallback cần biết mã của từng mặt hàng. Bạn sẽ thấy lỗi do SleepNightItemHeader cần ghi đè thuộc tính trừu tượng id.
abstract val id: Long
  1. Trong SleepNightItem, hãy ghi đè id để trả về nightId.
override val id = sleepNight.nightId
  1. Trong Header, hãy ghi đè id để trả về Long.MIN_VALUE, đây là một số rất nhỏ (tức là -2 lũy thừa 63). Vì vậy, điều này sẽ không bao giờ xung đột với bất kỳ nightId nào đang tồn tại.
override val id = Long.MIN_VALUE
  1. Mã hoàn tất của bạn sẽ trông như thế này và ứng dụng của bạn phải xây dựng mà không có lỗi.
sealed class DataItem {
    abstract val id: Long
    data class SleepNightItem(val sleepNight: SleepNight): DataItem()      {
        override val id = sleepNight.nightId
    }

    object Header: DataItem() {
        override val id = Long.MIN_VALUE
    }
}

Bước 2: Tạo ViewHolder cho Tiêu đề

  1. Tạo bố cục cho tiêu đề trong tệp tài nguyên bố cục mới có tên header.xml hiển thị TextView. Không có gì thú vị trong mã này, vì vậy, đây là mã.
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceLarge"
    android:text="Sleep Results"
    android:padding="8dp" />
  1. Trích xuất "Sleep Results" thành một tài nguyên chuỗi và gọi nó là header_text.
<string name="header_text">Sleep Results</string>
  1. Trong tệp SleepNightAdapter.kt, bên trong SleepNightAdapter, phía trên lớp ViewHolder, hãy tạo một lớp TextViewHolder mới. Lớp này tăng cường bố cục textview.xml và trả về một thực thể TextViewHolder. Vì bạn đã làm việc này trước đây, nên đây là mã và bạn sẽ phải nhập ViewR:
    class TextViewHolder(view: View): RecyclerView.ViewHolder(view) {
        companion object {
            fun from(parent: ViewGroup): TextViewHolder {
                val layoutInflater = LayoutInflater.from(parent.context)
                val view = layoutInflater.inflate(R.layout.header, parent, false)
                return TextViewHolder(view)
            }
        }
    }

Bước 3: Cập nhật SleepNightAdapter

Tiếp theo, bạn cần cập nhật nội dung khai báo của SleepNightAdapter. Thay vì chỉ hỗ trợ một loại ViewHolder, bạn cần sử dụng được bất kỳ loại chế độ xem nào.

Xác định loại mục

  1. Trong SleepNightAdapter.kt, ở cấp cao nhất, dưới câu lệnh import và trên SleepNightAdapter, hãy xác định hai hằng số cho loại chế độ xem.

    RecyclerView sẽ cần phân biệt loại chế độ xem của từng mục để có thể chỉ định chính xác giá trị cho chế độ xem.
    private val ITEM_VIEW_TYPE_HEADER = 0
    private val ITEM_VIEW_TYPE_ITEM = 1
  1. Bên trong SleepNightAdapter, hãy tạo một hàm để ghi đè getItemViewType() để trả về tiêu đề hoặc hằng số mục chính xác, tùy thuộc vào loại mục hiện tại.
override fun getItemViewType(position: Int): Int {
        return when (getItem(position)) {
            is DataItem.Header -> ITEM_VIEW_TYPE_HEADER
            is DataItem.SleepNightItem -> ITEM_VIEW_TYPE_ITEM
        }
    }

Cập nhật định nghĩa SleepnightAdapter

  1. Trong định nghĩa của SleepNightAdapter, hãy cập nhật đối số đầu tiên cho ListAdapter từ SleepNight thành DataItem.
  2. Trong định nghĩa của SleepNightAdapter, hãy thay đổi đối số chung thứ hai cho ListAdapter từ SleepNightAdapter.ViewHolder thành RecyclerView.ViewHolder. Bạn sẽ thấy một số lỗi về các nội dung cập nhật cần thiết và tiêu đề của lớp sẽ có dạng như dưới đây.
class SleepNightAdapter(val clickListener: SleepNightListener):
       ListAdapter<DataItem, RecyclerView.ViewHolder>(SleepNightDiffCallback()) {

Cập nhật onCreateViewHolder()

  1. Thay đổi chữ ký của onCreateViewHolder() để trả về RecyclerView.ViewHolder.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder
  1. Mở rộng phương thức triển khai phương thức onCreateViewHolder() để thử nghiệm và trả về trình giữ chế độ xem thích hợp cho từng loại mục. Phương thức cập nhật của bạn sẽ trông giống như mã bên dưới.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return when (viewType) {
            ITEM_VIEW_TYPE_HEADER -> TextViewHolder.from(parent)
            ITEM_VIEW_TYPE_ITEM -> ViewHolder.from(parent)
            else -> throw ClassCastException("Unknown viewType ${viewType}")
        }
    }

Cập nhật onBindViewHolder()

  1. Thay đổi loại thông số của onBindViewHolder() từ ViewHolder thành RecyclerView.ViewHolder.
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int)
  1. Thêm một điều kiện để chỉ chỉ định dữ liệu cho chủ sở hữu chế độ xem nếu chủ sở hữu là ViewHolder.
        when (holder) {
            is ViewHolder -> {...}
  1. Truyền loại đối tượng do getItem() trả về cho DataItem.SleepNightItem. Hàm onBindViewHolder() đã hoàn thành của bạn phải có dạng như thế này.
  override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (holder) {
            is ViewHolder -> {
                val nightItem = getItem(position) as DataItem.SleepNightItem
                holder.bind(nightItem.sleepNight, clickListener)
            }
        }
    }

Cập nhật các lệnh gọi lại diffUtil

  1. Thay đổi các phương thức trong SleepNightDiffCallback để sử dụng lớp DataItem mới thay vì SleepNight. Chặn cảnh báo lỗi như trong mã bên dưới.
class SleepNightDiffCallback : DiffUtil.ItemCallback<DataItem>() {
    override fun areItemsTheSame(oldItem: DataItem, newItem: DataItem): Boolean {
        return oldItem.id == newItem.id
    }
    @SuppressLint("DiffUtilEquals")
    override fun areContentsTheSame(oldItem: DataItem, newItem: DataItem): Boolean {
        return oldItem == newItem
    }
}

Thêm và gửi tiêu đề

  1. Bên trong SleepNightAdapter, bên dưới onCreateViewHolder(), hãy xác định hàm addHeaderAndSubmitList() như bên dưới. Hàm này lấy danh sách SleepNight. Thay vì dùng submitList() do ListAdapter cung cấp, để gửi danh sách của bạn, bạn phải dùng hàm này để thêm tiêu đề rồi gửi danh sách.
fun addHeaderAndSubmitList(list: List<SleepNight>?) {}
  1. Bên trong addHeaderAndSubmitList(), nếu danh sách được chuyển là null, hãy chỉ trả về tiêu đề, nếu không, hãy đính kèm tiêu đề vào đầu danh sách, sau đó gửi danh sách.
val items = when (list) {
                null -> listOf(DataItem.Header)
                else -> listOf(DataItem.Header) + list.map { DataItem.SleepNightItem(it) }
            }
submitList(items)
  1. Mở SleepTrackerFragment.kt rồi thay đổi lệnh gọi thành submitList() thành addHeaderAndSubmitList().
  1. Chạy ứng dụng của bạn và quan sát cách tiêu đề hiển thị dưới dạng mục đầu tiên trong danh sách các mục ngủ.

Có hai vấn đề cần được khắc phục cho ứng dụng này. Một điều có thể hiển thị và một nội dung thì không.

  • Tiêu đề sẽ hiển thị ở góc trên cùng bên trái và không dễ phân biệt.
  • Thao tác này không ảnh hưởng nhiều đến danh sách ngắn có một tiêu đề, nhưng bạn không nên thao tác với danh sách trong addHeaderAndSubmitList() trên chuỗi giao diện người dùng. Hãy tưởng tượng danh sách với hàng trăm mục, nhiều tiêu đề và logic để quyết định vị trí cần chèn mục. Tác vụ này thuộc về một coroutine.

Thay đổi addHeaderAndSubmitList() để sử dụng coroutine:

  1. Ở cấp cao nhất trong lớp SleepNightAdapter, hãy xác định một CoroutineScope bằng Dispatchers.Default.
private val adapterScope = CoroutineScope(Dispatchers.Default)
  1. Trong addHeaderAndSubmitList(), hãy chạy coroutine trong adapterScope để thao tác với danh sách. Sau đó, chuyển sang ngữ cảnh Dispatchers.Main để gửi danh sách như trong mã bên dưới.
 fun addHeaderAndSubmitList(list: List<SleepNight>?) {
        adapterScope.launch {
            val items = when (list) {
                null -> listOf(DataItem.Header)
                else -> listOf(DataItem.Header) + list.map { DataItem.SleepNightItem(it) }
            }
            withContext(Dispatchers.Main) {
                submitList(items)
            }
        }
    }
  1. Mã của bạn phải tạo và chạy và bạn sẽ không thấy bất kỳ sự khác biệt nào.

Hiện tại, tiêu đề có cùng chiều rộng với các mục khác trên lưới, chiếm một chiều ngang và dọc. Toàn bộ lưới vừa với 3 mục có chiều rộng một khoảng theo chiều ngang, vì vậy, tiêu đề phải sử dụng 3 khoảng ngang.

Để sửa chiều rộng tiêu đề, bạn cần phải cho GridLayoutManager biết thời điểm cần mở rộng dữ liệu trên tất cả các cột. Bạn có thể thực hiện việc này bằng cách thiết lập SpanSizeLookup trên GridLayoutManager. Đây là một đối tượng cấu hình mà GridLayoutManager sử dụng để xác định số lượng khoảng thời gian để dùng cho từng mục trong danh sách.

  1. Mở SleepTrackerFragment.kt.
  2. Tìm mã mà bạn xác định manager, ở cuối onCreateView().
val manager = GridLayoutManager(activity, 3)
  1. Bên dưới manager, hãy xác định manager.spanSizeLookup (như minh họa). Bạn cần tạo objectsetSpanSizeLookup không lấy hàm lambda. Để tạo object trong Kotlin, hãy nhập object : classname, trong trường hợp này là GridLayoutManager.SpanSizeLookup.
manager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
}
  1. Bạn có thể gặp lỗi với trình biên dịch để gọi hàm dựng. Nếu bạn làm như vậy, hãy mở trình đơn ý định bằng Option+Enter (Mac) hoặc Alt+Enter (Windows) để áp dụng lệnh gọi hàm dựng.
  1. Sau đó, bạn sẽ gặp lỗi trên object cho biết bạn cần phải ghi đè các phương thức. Đặt con trỏ trên object, nhấn Option+Enter (Mac) hoặc Alt+Enter (Windows) để mở trình đơn ý định, sau đó ghi đè phương thức getSpanSize().
  1. Trong phần nội dung của getSpanSize(), hãy trả về kích thước khoảng bên phải cho mỗi vị trí. Vị trí 0 có kích thước khoảng là 3 và các vị trí khác có kích thước khoảng là 1. Mã hoàn tất sẽ có dạng như mã bên dưới:
    manager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
            override fun getSpanSize(position: Int) =  when (position) {
                0 -> 3
                else -> 1
            }
        }
  1. Để cải thiện giao diện tiêu đề của bạn, hãy mở header.xml và thêm mã này vào tệp bố cục header.xml.
android:textColor="@color/white_text_color"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:background="@color/colorAccent"
  1. Chạy ứng dụng của bạn. Ứng dụng phải giống như ảnh chụp màn hình dưới đây.

Xin chúc mừng! Bạn đã hoàn tất.

Dự án Android Studio: RecyclerViewHeaders

  • Tiêu đề thường là một mục kéo dài chiều rộng của một danh sách và có vai trò là tiêu đề hoặc dấu phân tách. Một danh sách có thể có một tiêu đề để mô tả nội dung mục hoặc nhiều tiêu đề để nhóm các mục và tách các mục khỏi nhau.
  • RecyclerView có thể sử dụng nhiều chủ sở hữu chế độ xem để đáp ứng nhóm các mục không đồng nhất; ví dụ: tiêu đề và mục danh sách.
  • Một cách để thêm tiêu đề là sửa đổi bộ chuyển đổi để sử dụng ViewHolder khác bằng cách kiểm tra các chỉ mục mà tiêu đề cần hiển thị. Adapter chịu trách nhiệm theo dõi tiêu đề.
  • Một cách khác để thêm tiêu đề là sửa đổi tập dữ liệu sao lưu (danh sách) cho lưới dữ liệu của bạn, đó là những gì bạn đã làm trong lớp học lập trình này.

Sau đây là các bước chính để thêm tiêu đề:

  • Trừu tượng dữ liệu trong danh sách của bạn bằng cách tạo DataItem có thể chứa tiêu đề hoặc dữ liệu.
  • Tạo một chế độ xem có bố cục cho tiêu đề trong bộ chuyển đổi.
  • Cập nhật bộ chuyển đổi và phương thức để sử dụng bất kỳ loại RecyclerView.ViewHolder nào.
  • Trong onCreateViewHolder(), hãy trả về đúng loại giá trị xem cho mục dữ liệu.
  • Hãy cập nhật SleepNightDiffCallback để làm việc với lớp DataItem.
  • Tạo một hàm addHeaderAndSubmitList() sử dụng coroutine để thêm tiêu đề vào tập dữ liệu rồi gọi submitList().
  • Triển khai GridLayoutManager.SpanSizeLookup() để chỉ làm cho tiêu đề rộng ba nhịp.

Khóa học từ Udacity:

Tài liệu dành cho nhà phát triển Android:

Phần này liệt kê các bài tập về nhà có thể được giao cho học viên đang làm việc qua lớp học lập trình này trong khóa học do người hướng dẫn tổ chức. Người hướng dẫn có thể làm những việc sau:

  • Giao bài tập về nhà nếu được yêu cầu.
  • Trao đổi với học viên cách nộp bài tập về nhà.
  • Chấm điểm bài tập về nhà.

Người hướng dẫn có thể sử dụng những đề xuất này ít hay nhiều tùy ý. Do đó, họ có thể thoải mái giao bất kỳ bài tập về nhà nào khác mà họ cảm thấy phù hợp.

Nếu bạn đang tự mình làm việc qua lớp học lập trình này, hãy thoải mái sử dụng các bài tập về nhà này để kiểm tra kiến thức của bạn.

Trả lời những câu hỏi này

Câu hỏi 1

Câu nào sau đây đúng về ViewHolder?

▢ Một bộ chuyển đổi có thể sử dụng nhiều lớp ViewHolder để lưu giữ tiêu đề và nhiều loại dữ liệu.

▢ Bạn có thể có duy nhất một trình xem chế độ xem cho dữ liệu và một máy chủ xem cho tiêu đề.

RecyclerView có hỗ trợ nhiều loại tiêu đề, nhưng dữ liệu phải thống nhất.

▢ Khi thêm tiêu đề, bạn sẽ phân lớp con RecyclerView để chèn tiêu đề vào đúng vị trí.

Câu hỏi 2

Khi nào bạn nên sử dụng coroutine với RecyclerView? Chọn tất cả câu đúng.

▢ Không bao giờ. RecyclerView là một phần tử giao diện người dùng và không được sử dụng coroutine.

▢ Sử dụng coroutine cho các tác vụ chạy trong thời gian dài có thể làm chậm giao diện người dùng.

▢ Các thao tác với danh sách có thể mất nhiều thời gian và bạn luôn phải thực hiện các thao tác đó bằng coroutine.

▢ Sử dụng coroutine với các hàm tạm ngưng để tránh chặn chuỗi chính.

Câu hỏi 3

Bạn KHÔNG phải làm những việc nào sau đây khi sử dụng nhiều ViewHolder?

▢ Trong ViewHolder, hãy cung cấp nhiều tệp bố cục để tăng cường nếu cần.

▢ Trong onCreateViewHolder(), hãy trả về đúng loại chủ sở hữu chế độ xem cho mục dữ liệu.

▢ Trong onBindViewHolder(), chỉ liên kết dữ liệu nếu chủ sở hữu chế độ xem là loại chủ sở hữu chế độ xem chính xác cho mục dữ liệu.

▢ Giới thiệu chung về chữ ký của lớp bộ chuyển đổi để chấp nhận bất kỳ RecyclerView.ViewHolder nào.

Bắt đầu bài học tiếp theo: 8.1 Lấy dữ liệu từ Internet

Để biết đường liên kết đến các lớp học lập trình khác trong khóa học này, hãy xem trang đích của các lớp học lập trình cơ bản về Android Kotlin.