如何解决当数据库中的单个数据更改时,RecyclerView会设置所有项目
我正在使用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个项目。我正在使用观察方法:
设置数据 viewModel.last30.observe(viewLifecycleOwner,{
adapter.submitList(it)
}
问题:
- 单击“喜欢”按钮时,“回收者”视图将刷新其所有内容,并滚动到第一项。
已编辑: SubmitList(list:List)方法:
fun submitList(persons: List<Person>) {
val diffResult: DiffUtil.DiffResult = DiffUtil.calculateDiff(
ApodGalleryAdapterDiffCallback(
this.persons,persons
)
)
this.persons = person
diffResult.dispatchUpdatesTo(this)
}
DiffUtill类:
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 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] == newList[newItemPosition]
}
}
我已经覆盖了Data类的equals()
方法:
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
始终返回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运行得很好。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。