Final Results
Our todo_row layout resource should look like:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:clickable="true"
  android:focusable="true"
  android:background="?attr/selectableItemBackground">
  <CheckBox
    android:id="@+id/isCompleted"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="8dp"
    android:layout_marginTop="8dp"
    android:layout_marginBottom="8dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
  <TextView
    android:id="@+id/desc"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginStart="8dp"
    android:layout_marginTop="8dp"
    android:layout_marginEnd="8dp"
    android:layout_marginBottom="8dp"
    android:ellipsize="end"
    android:maxLines="3"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toEndOf="@+id/isCompleted"
    app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>RosterAdapter should look like:
package com.commonsware.todo
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import com.commonsware.todo.databinding.TodoRowBinding
class RosterAdapter(private val inflater: LayoutInflater) :
  ListAdapter<ToDoModel, RosterRowHolder>(DiffCallback) {
  override fun onCreateViewHolder(
    parent: ViewGroup,
    viewType: Int
  ) = RosterRowHolder(TodoRowBinding.inflate(inflater, parent, false))
  override fun onBindViewHolder(holder: RosterRowHolder, position: Int) {
    holder.bind(getItem(position))
  }
}
private object DiffCallback : DiffUtil.ItemCallback<ToDoModel>() {
  override fun areItemsTheSame(oldItem: ToDoModel, newItem: ToDoModel) =
    oldItem.id == newItem.id
  override fun areContentsTheSame(oldItem: ToDoModel, newItem: ToDoModel) =
    oldItem.isCompleted == newItem.isCompleted &&
        oldItem.description == newItem.description
}
…and RosterRowHolder should look like:
package com.commonsware.todo
import androidx.recyclerview.widget.RecyclerView
import com.commonsware.todo.databinding.TodoRowBinding
class RosterRowHolder(private val binding: TodoRowBinding) :
  RecyclerView.ViewHolder(binding.root) {
  fun bind(model: ToDoModel) {
    binding.apply {
      isCompleted.isChecked = model.isCompleted
      desc.text = model.description
    }
  }
}Finally, RosterListFragment now should look like:
package com.commonsware.todo
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.commonsware.todo.databinding.TodoRosterBinding
import org.koin.androidx.viewmodel.ext.android.viewModel
class RosterListFragment : Fragment() {
  private val motor: RosterMotor by viewModel()
  private var binding: TodoRosterBinding? = null
  override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
  ): View = TodoRosterBinding.inflate(inflater, container, false)
    .also { binding = it }
    .root
  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    val adapter = RosterAdapter(layoutInflater)
    binding?.items?.apply {
      setAdapter(adapter)
      layoutManager = LinearLayoutManager(context)
      addItemDecoration(
        DividerItemDecoration(
          activity,
          DividerItemDecoration.VERTICAL
        )
      )
    }
    adapter.submitList(motor.items)
    binding?.empty?.visibility = View.GONE
  }
  override fun onDestroyView() {
    binding = null
    super.onDestroyView()
  }
}Prev Table of Contents Next
This book is licensed under the Creative Commons Attribution-ShareAlike 4.0 International license.