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

ListAdapter  |  Android Developers