1. ホーム
  2. android

[解決済み] RecyclerViewのListAdapterのアイテムが更新されない

2022-06-10 10:19:56

質問

新しいサポートライブラリを使用しています ListAdapter . 以下は、私のアダプタのコードです。

class ArtistsAdapter : ListAdapter<Artist, ArtistsAdapter.ViewHolder>(ArtistsDiff()) {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(parent.inflate(R.layout.item_artist))
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(getItem(position))
    }

    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        fun bind(artist: Artist) {
            itemView.artistDetails.text = artist.artistAlbums
                    .plus(" Albums")
                    .plus(" \u2022 ")
                    .plus(artist.artistTracks)
                    .plus(" Tracks")
            itemView.artistName.text = artist.artistCover
            itemView.artistCoverImage.loadURL(artist.artistCover)
        }
    }
}

でアダプタを更新しています。

musicViewModel.getAllArtists().observe(this, Observer {
            it?.let {
                artistAdapter.submitList(it)
            }
        })

私のdiffクラス

class ArtistsDiff : DiffUtil.ItemCallback<Artist>() {
    override fun areItemsTheSame(oldItem: Artist?, newItem: Artist?): Boolean {
        return oldItem?.artistId == newItem?.artistId
    }

    override fun areContentsTheSame(oldItem: Artist?, newItem: Artist?): Boolean {
        return oldItem == newItem
    }
}

何が起こっているかというと、submitList が最初に呼ばれたとき、アダプタはすべての項目をレンダリングします。しかし、オブジェクトのプロパティを更新して submitList が再度呼ばれたとき、変更されたビューを再レンダリングしません。

リストをスクロールするとビューが再レンダリングされ、その際に bindView()

また、私は adapter.notifyDatasSetChanged() を呼び出すと、更新された値でビューがレンダリングされることに気づきましたが、私は notifyDataSetChanged() を呼び出したくありません。なぜなら、リストアダプタには diff ユーティリティが組み込まれているからです。

どなたか教えてください。

どのように解決するのですか?

編集:なぜこのようなことが起こるのか、それは私のポイントではなかったと理解しています。私が言いたいのは、少なくとも警告を出すか、あるいは notifyDataSetChanged() 関数を呼び出す必要があるということです。なぜなら、どうやら私は submitList(...) 関数を呼び出しているからです。submitList()が黙って呼び出しを無視することがわかるまで、人々が何時間も何が悪かったのか考えようとしているのは確かです。

これは Google の奇妙なロジックのせいです。そのため、同じリストをアダプタに渡しても、アダプタは DiffUtil .

public void submitList(final List<T> newList) {
    if (newList == mList) {
        // nothing to do
        return;
    }
....
}

私は本当にこの全体のポイントを理解していない ListAdapter が同じリストの変更を扱えないのであれば、その意味が分かりません。リスト上の項目を変更したい場合は ListAdapter に渡したリストの項目を変更し、その変更を確認したい場合は、 リストの深いコピーを作成するか、あるいは通常の RecyclerView を使うか、あるいは自分で DiffUtill クラスに変換します。