〈kotlin〉ListAdapter
Android studioでkotlinを使ってAndroidアプリ作成の勉強中。
以前RecyclerViewの使い方について記録した。
〈kotlin〉Android studio使い方メモ10:RecyclerView - ゆるプログラミング日記
ここではRecuclerView.Adapterを継承してアダプターを作成したが、
ListAdapterを使うのが便利そうだったのでまとめてみる。
ListAdapterとは
RecuclerView.AdapterにAsyncListDifferがラップされたクラス。
AsyncListDifferは、バックグラウンドスレッドで DiffUtil を使って
元のリストと与えられたリストの差を計算するためのヘルパー。
差分が存在する場合に、変更箇所のみを更新してくれる。
実装
サンプルコードは以下のcodelabの一部変更。
Room によるデータの読み取りと更新 | Android Developers
ListAdapterを継承したクラスを作成する。
ListAdapterにはViewHolderクラスとDiffUtil.ItemCallbackのインスタンスを渡す必要があり、
どちらもクラス内で定義する。
onCreateViewHolder()メソッドとonBindViewHolder()メソッドをオーバーライドする。
class ItemListAdapter(private val onItemClicked: (Item) -> Unit) : ListAdapter<Item, ItemListAdapter.ItemViewHolder>(DiffCallback) { //クリックイベントはfragmentでadapterを定義する時にラムダで渡す override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { val view = ItemListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false) return ItemViewHolder(view) } override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { val current = getItem(position) holder.itemView.setOnClickListener { onItemClicked(current) } holder.bind(current) } //ViewHolder、ビューに値をセットするbind()を定義する class ItemViewHolder(private var binding: ItemListItemBinding) : RecyclerView.ViewHolder(binding.root) { fun bind(item: Item) { binding.apply { itemName.text = item.itemName } } } //DiffUtil.ItemCallbackのインスタンス companion object { private val DiffCallback = object : DiffUtil.ItemCallback<Item>() { //2つのアイテムが全く同じものか override fun areItemsTheSame(oldItem: Item, newItem: Item): Boolean { return oldItem === newItem } //2つのアイテムの内容が同じものか override fun areContentsTheSame(oldItem: Item, newItem: Item): Boolean { return oldItem.itemName == newItem.itemName } }
ListAdapterを使う
adapterを使用するfragment内で定義する。
リストを更新するためにはsubmitList()で新しくセットするリストを渡す。
class ItemListFragment : Fragment() { ... override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val adapter = ItemListAdapter{ //引数onItemClickedをラムダで渡す、 val action = ItemListFragmentDirections.actionItemListFragmentToItemDetailFragment(it.id) this.findNavController().navigate(action) } binding.recyclerView.adapter = adapter viewModel.allItems.observe(this.viewLifecycleOwner){ items -> items.let { adapter.submitList(it) } }