मैं इस तरह डेटाबेस से 30 आइटम लाने के लिए LiveData का उपयोग कर रहा हूं:

@Query("SELECT * FROM table ORDER BY id DESC LIMIT 30")
fun getLast30(): LiveData<List<Person>>

प्रत्येक पुनरावर्तक दृश्य आइटम में एक समान बटन होता है और मेरे पास एडेप्टर में एक इंटरफ़ेस होता है:

interface OnItemClickedAdapter {
    fun onFavButtonClicked(position: Int)
}

अंत जब जैसे बटन पर क्लिक किया गया तो मैं डेटाबेस में एक आइटम अपडेट कर रहा हूं। जैसा कि मैं लाइवडाटा का उपयोग कर रहा हूं, यह अद्यतन 30 आइटम ला रहा है। मैं उस डेटा को निरीक्षण विधि का उपयोग करके सेट कर रहा हूं:

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

डिफ्यूटिल क्लास:

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].url == newList[newItemPosition].url
    }

    override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean {
        return oldList[oldItemPosition] == newList[newItemPosition]
    }

}

मैंने अपने डेटा वर्ग की 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
}
1
Javlon 23 सितंबर 2020, 13:17

2 जवाब

सबसे बढ़िया उत्तर

मैं 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
    })

इस ब्लॉक की अंतिम पंक्ति में, मैं एडॉप्टर को बार-बार सेट कर रहा हूं जब लाइवडाटा बदलता है। DiffUtill पूरी तरह से काम कर रहा था।

0
Javlon 24 सितंबर 2020, 08:51

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
}
1
Ehsan msz 23 सितंबर 2020, 14:16