RecyclerView 设置数据库中单个数据更改时的所有项目
RecyclerView sets all the items when single data changed in database
我正在使用 LiveData 从数据库中获取 30 个项目,如下所示:
@Query("SELECT * FROM table ORDER BY id DESC LIMIT 30")
fun getLast30(): LiveData<List<Person>>
每个回收站视图项目都有一个喜欢的按钮,我在适配器中有一个接口:
interface OnItemClickedAdapter {
fun onFavButtonClicked(position: Int)
}
单击“赞”按钮时结束我正在更新数据库中的单个项目。当我使用 LiveData 时,它正在获取更新的 30 个项目。我正在使用 observe 方法设置该数据:
viewModel.last30.observe(viewLifecycleOwner, {
adapter.submitList(it)
}
问题:
- 单击“赞”按钮后,回收站视图会刷新其所有内容并滚动到第一项。
已编辑:
提交列表(列表:列表)方法:
fun submitList(persons: List<Person>) {
val diffResult: DiffUtil.DiffResult = DiffUtil.calculateDiff(
ApodGalleryAdapterDiffCallback(
this.persons,
persons
)
)
this.persons = person
diffResult.dispatchUpdatesTo(this)
}
DiffUtill class:
class PersonAdapterDiffCallback(var oldList: List<Person>, var newList: List<Person>) :
DiffUtil.Callback() {
override fun getOldListSize(): Int {
return oldList.size
}
override fun getNewListSize(): Int {
return newList.size
}
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition].url == newList[newItemPosition].url
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition] == newList[newItemPosition]
}
}
适配器class:
class ApodGalleryAdapter() :
RecyclerView.Adapter<ApodGalleryAdapter.ApodGalleryViewHolder>() {
var onItemClickedGalleryAdapter: OnItemClickedGalleryAdapter? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ApodGalleryViewHolder {
return ApodGalleryViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.item_apod_gallery, parent, false),
onItemClickedGalleryAdapter
)
}
private var apods: List<Apod> = ArrayList()
override fun getItemCount(): Int {
return apods.size
}
override fun onBindViewHolder(holder: ApodGalleryViewHolder, position: Int) {
holder.bindData(apods[position], position)
}
fun submitList(apods: List<Apod>) {
val diffResult: DiffUtil.DiffResult = DiffUtil.calculateDiff(
ApodGalleryAdapterDiffCallback(
this.apods,
apods
)
)
this.apods = apods
diffResult.dispatchUpdatesTo(this)
}
class ApodGalleryViewHolder(
itemView: View,
var onItemClickedGalleryAdapter: OnItemClickedGalleryAdapter?
) :
RecyclerView.ViewHolder(itemView) {
private val apodImage: ImageView = itemView.image_item_apod
private val apodTitle: TextView = itemView.title_item_apod
private val apodDescription: TextView = itemView.description_item_apod
private val apodCopyright: TextView = itemView.copyright_item_apod
fun bindData(apod: Apod, position: Int) {
when {
apod.url.endsWith(".jpg") -> {
Glide.with(apodImage.context)
.load(apod.url)
.placeholder(R.drawable.transparent)
.into(apodImage)
}
apod.url.contains("youtube") -> {
Glide.with(apodImage.context)
.load(getThumbnailUrl(apod.url))
.placeholder(R.drawable.transparent)
.into(apodImage)
}
else -> {
apodImage.setImageResource(R.drawable.transparent)
}
}
apodTitle.text = apod.title
apodDescription.text = apod.explanation
apodCopyright.text = apod.copyright
if (apod.isLiked) {
itemView.fav_button_item_apod_gallery.setImageResource(R.drawable.ic_round_favorite_24)
} else {
itemView.fav_button_item_apod_gallery.setImageResource(R.drawable.ic_round_favorite_border_24)
}
itemView.setOnClickListener {
onItemClickedGalleryAdapter?.onClick(apod.date)
}
itemView.fav_button_item_apod_gallery.setOnClickListener {
onItemClickedGalleryAdapter?.onFavButtonClicked(position)
}
}
}
}
interface OnItemClickedGalleryAdapter {
fun onClick(date: String)
fun onFavButtonClicked(position: Int)
}
class ApodGalleryAdapterDiffCallback(var oldList: List<Apod>, var newList: List<Apod>) :
DiffUtil.Callback() {
override fun getOldListSize(): Int {
return oldList.size
}
override fun getNewListSize(): Int {
return newList.size
}
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition].url == newList[newItemPosition].url
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition] == newList[newItemPosition]
}
}
我已经覆盖了我的数据的 equals()
方法 class:
override fun equals(other: Any?): Boolean {
if (javaClass != other?.javaClass)
return false
other as Apod
if (id != other.id)
return false
if (copyright != other.copyright)
return false
if (date != other.date)
return false
if (explanation != other.explanation)
return false
if (hdUrl != other.hdUrl)
return false
if (media_type != other.media_type)
return false
if (service_version != other.service_version)
return false
if (url != other.url)
return false
if (isLiked != other.isLiked)
return false
return true
}
在 DiffUtil
实施中,areContentsTheSame
总是 returns false
.
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition] == newList[newItemPosition] // always returns false
}
你必须像这样检查每个变量:
//for example
data class Person(
val name:String,
val age:Int
)
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
val oldItem = oldList[oldItemPosition]
val newItem = newList[newItemPosition]
return oldItem.name.equals(newItem.name) &&
oldItem.age == newItem.age
}
我通过 liveData、DiffUtill 和 adapter.notifyItemChanged(position)
彻底搜索了解决方案
真正的问题出在我的观察者块中:
viewModel.apod30Days.observe(viewLifecycleOwner, {
adapter.submitList(it)
adapter.onItemClickedGalleryAdapter = object : OnItemClickedGalleryAdapter {
override fun onClick(date: String) {
val intent =
Intent(requireActivity().applicationContext, DetailsActivity::class.java)
intent.putExtra(DetailsActivity.APOD_DATE_KEY, date)
startActivity(intent)
}
override fun onFavButtonClicked(position: Int) {
val apod = it[position]
apod.isLiked = !apod.isLiked
viewModel.updateApod(apod)
adapter.notifyItemChanged(position)
}
}
if (it.size < 30)
viewModel.setLast30Apods()
binding.apodViewPager.adapter = adapter
})
在此块的最后一行,我在 liveData 更改时一次又一次地设置适配器。 DiffUtill 运行良好。
我正在使用 LiveData 从数据库中获取 30 个项目,如下所示:
@Query("SELECT * FROM table ORDER BY id DESC LIMIT 30")
fun getLast30(): LiveData<List<Person>>
每个回收站视图项目都有一个喜欢的按钮,我在适配器中有一个接口:
interface OnItemClickedAdapter {
fun onFavButtonClicked(position: Int)
}
单击“赞”按钮时结束我正在更新数据库中的单个项目。当我使用 LiveData 时,它正在获取更新的 30 个项目。我正在使用 observe 方法设置该数据:
viewModel.last30.observe(viewLifecycleOwner, {
adapter.submitList(it)
}
问题:
- 单击“赞”按钮后,回收站视图会刷新其所有内容并滚动到第一项。
已编辑: 提交列表(列表:列表)方法:
fun submitList(persons: List<Person>) {
val diffResult: DiffUtil.DiffResult = DiffUtil.calculateDiff(
ApodGalleryAdapterDiffCallback(
this.persons,
persons
)
)
this.persons = person
diffResult.dispatchUpdatesTo(this)
}
DiffUtill class:
class PersonAdapterDiffCallback(var oldList: List<Person>, var newList: List<Person>) :
DiffUtil.Callback() {
override fun getOldListSize(): Int {
return oldList.size
}
override fun getNewListSize(): Int {
return newList.size
}
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition].url == newList[newItemPosition].url
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition] == newList[newItemPosition]
}
}
适配器class:
class ApodGalleryAdapter() :
RecyclerView.Adapter<ApodGalleryAdapter.ApodGalleryViewHolder>() {
var onItemClickedGalleryAdapter: OnItemClickedGalleryAdapter? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ApodGalleryViewHolder {
return ApodGalleryViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.item_apod_gallery, parent, false),
onItemClickedGalleryAdapter
)
}
private var apods: List<Apod> = ArrayList()
override fun getItemCount(): Int {
return apods.size
}
override fun onBindViewHolder(holder: ApodGalleryViewHolder, position: Int) {
holder.bindData(apods[position], position)
}
fun submitList(apods: List<Apod>) {
val diffResult: DiffUtil.DiffResult = DiffUtil.calculateDiff(
ApodGalleryAdapterDiffCallback(
this.apods,
apods
)
)
this.apods = apods
diffResult.dispatchUpdatesTo(this)
}
class ApodGalleryViewHolder(
itemView: View,
var onItemClickedGalleryAdapter: OnItemClickedGalleryAdapter?
) :
RecyclerView.ViewHolder(itemView) {
private val apodImage: ImageView = itemView.image_item_apod
private val apodTitle: TextView = itemView.title_item_apod
private val apodDescription: TextView = itemView.description_item_apod
private val apodCopyright: TextView = itemView.copyright_item_apod
fun bindData(apod: Apod, position: Int) {
when {
apod.url.endsWith(".jpg") -> {
Glide.with(apodImage.context)
.load(apod.url)
.placeholder(R.drawable.transparent)
.into(apodImage)
}
apod.url.contains("youtube") -> {
Glide.with(apodImage.context)
.load(getThumbnailUrl(apod.url))
.placeholder(R.drawable.transparent)
.into(apodImage)
}
else -> {
apodImage.setImageResource(R.drawable.transparent)
}
}
apodTitle.text = apod.title
apodDescription.text = apod.explanation
apodCopyright.text = apod.copyright
if (apod.isLiked) {
itemView.fav_button_item_apod_gallery.setImageResource(R.drawable.ic_round_favorite_24)
} else {
itemView.fav_button_item_apod_gallery.setImageResource(R.drawable.ic_round_favorite_border_24)
}
itemView.setOnClickListener {
onItemClickedGalleryAdapter?.onClick(apod.date)
}
itemView.fav_button_item_apod_gallery.setOnClickListener {
onItemClickedGalleryAdapter?.onFavButtonClicked(position)
}
}
}
}
interface OnItemClickedGalleryAdapter {
fun onClick(date: String)
fun onFavButtonClicked(position: Int)
}
class ApodGalleryAdapterDiffCallback(var oldList: List<Apod>, var newList: List<Apod>) :
DiffUtil.Callback() {
override fun getOldListSize(): Int {
return oldList.size
}
override fun getNewListSize(): Int {
return newList.size
}
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition].url == newList[newItemPosition].url
}
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition] == newList[newItemPosition]
}
}
我已经覆盖了我的数据的 equals()
方法 class:
override fun equals(other: Any?): Boolean {
if (javaClass != other?.javaClass)
return false
other as Apod
if (id != other.id)
return false
if (copyright != other.copyright)
return false
if (date != other.date)
return false
if (explanation != other.explanation)
return false
if (hdUrl != other.hdUrl)
return false
if (media_type != other.media_type)
return false
if (service_version != other.service_version)
return false
if (url != other.url)
return false
if (isLiked != other.isLiked)
return false
return true
}
在 DiffUtil
实施中,areContentsTheSame
总是 returns false
.
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
return oldList[oldItemPosition] == newList[newItemPosition] // always returns false
}
你必须像这样检查每个变量:
//for example
data class Person(
val name:String,
val age:Int
)
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
val oldItem = oldList[oldItemPosition]
val newItem = newList[newItemPosition]
return oldItem.name.equals(newItem.name) &&
oldItem.age == newItem.age
}
我通过 liveData、DiffUtill 和 adapter.notifyItemChanged(position)
真正的问题出在我的观察者块中:
viewModel.apod30Days.observe(viewLifecycleOwner, {
adapter.submitList(it)
adapter.onItemClickedGalleryAdapter = object : OnItemClickedGalleryAdapter {
override fun onClick(date: String) {
val intent =
Intent(requireActivity().applicationContext, DetailsActivity::class.java)
intent.putExtra(DetailsActivity.APOD_DATE_KEY, date)
startActivity(intent)
}
override fun onFavButtonClicked(position: Int) {
val apod = it[position]
apod.isLiked = !apod.isLiked
viewModel.updateApod(apod)
adapter.notifyItemChanged(position)
}
}
if (it.size < 30)
viewModel.setLast30Apods()
binding.apodViewPager.adapter = adapter
})
在此块的最后一行,我在 liveData 更改时一次又一次地设置适配器。 DiffUtill 运行良好。