LoginSignup
14
11

More than 5 years have passed since last update.

RecyclerViewでListAdapterを使う

Posted at

Google I/O 2018 Android Jetpack: what’s new in Android Support LibraryのセッションであがってきたRecyclerViewの新しい機能、ListAdapterとRecyclerViewについて紹介します。

ListAdapterとは

ListAdapterはSupport Library 27.1.0で提供されたAPIです。ListAdapterはGoogle I/O 2018のAndroid Jetpack: what’s new in Android Support LibraryのセッションとAndroid Jetpack: manage infinite lists with RecyclerView and Pagingのセッションで次のような特徴が紹介されました。

・不変(Immutable)リストの動作
・Diffutilの利用によってコードが簡略される
・アニメーションを提供

ListApdaterは内部的にリストを読むだけの不変オブジェクトとして扱います。従って渡されたリストで直接的な要素の変更を許さず、もし変更するとしてもアップデートは反映されません。リストで要素が修正、追加、削除、移動が発生した場合、必ず変更が反映された新しいリストをListAdpaterへ渡します。バックグラウンドスレッドでリストが変更される場合、内部的にnotifyItem()関数が呼び出され、利用者はアップデートされたRecyclerViewを確認できます。これは既存のRecyclerViewアダプタとの違いであり、ListAdapterの特徴です。

こういう構造でLiveData又はObservableを利用し、リストの変更されたデータを読み、変更されたリストをListAdapterで実装することができます。

ListAdapterの状態を変更するためのAPIは新しいリストを設定する submitList(val lsit: List<T>)の関数しかありません。内部動作に比べて外部のインターフェースは極端に単純です。

DiffUtil.ItemCallbackの実装

ListAdapterは2つのリストを比較するためのコンストラクタのパラメータで、 Diffuil.Itemcallbackが必要です。
Diffuil.Itemcallbackの実装は以下のようになります。

private val diffCallback = object : DiffUtil.ItemCallback<Int>() {
  override fun areItemsTheSame(oldItem: Int, newItem: Int) =
          oldItem == newItem // check uniqueness

  override fun areContentsTheSame(oldItem: Int, newItem: Int) =
          oldItem == newItem // check contents
}

実装すべきメソッドは以下の2つになります。

areItemsTheSame
2つのアイテム自体が同じものであるかを判定します。

areContentsTheSame
2つのアイテムのデータ内容が同じであるかを判定します。

ListAdapterの実装

ListAdapterの実装ですが、DiffUtil.ItemCallbackインスタンスを渡せばOKです。

private val adapter: ListAdapter<Int, MyViewHolder> = object : ListAdapter<Int, MyViewHolder>(diffCallback) {
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) =
                MyViewHolder(parent)

        override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
            holder.bindTo(getItem(position))
        }
    }
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val recyclerView = findViewById<RecyclerView>(R.id.recyclerView)
        recyclerView.adapter = adapter.apply {
            registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
                override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
                    recyclerView.scrollToPosition(0)
                }
            })
        }

        numbers.apply {
            value = listOf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
            observe(this@MainActivity, Observer<List<Int>> {
                adapter.submitList(it)
            })
        }
    }

まとめ

ListAdapterを使用すると、より簡単なコードでRecyclerViewを利用することができます。

14
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
11