如何在 RecyclerAdapter ViewHolder 上实现 LifecycleOwner?

How to Implement LifecycleOwner on a RecyclerAdapter ViewHolder?

我需要从 RecyclerAdapter ViewHolder 中的 ViewModel 观察 LiveData。背后的原因就不说了。 为此,我创建了一个实现 LifeycleOwner 的自定义 ViewHolder,并设法正确调用生命周期事件,除了“Lifecycle.State.DESTROYED

这是我最终得到的代码:

自定义适配器:

abstract class LifecyclePagingDataAdapter<T: Any, VH: LifecycleViewHolder>(diffCallback: DiffUtil.ItemCallback<T>) : PagingDataAdapter<T, VH>(diffCallback) {

    override fun onViewAttachedToWindow(holder: VH) {
        super.onViewAttachedToWindow(holder)
        holder.onAppear()
    }

    override fun onViewDetachedFromWindow(holder: VH) {
        super.onViewDetachedFromWindow(holder)
        holder.onDisappear()
    }
}

自定义 ViewHolder:

abstract class LifecycleViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), LifecycleOwner {
    private val lifecycleRegistry = LifecycleRegistry(this)

    init {
        lifecycleRegistry.currentState = Lifecycle.State.INITIALIZED
        lifecycleRegistry.currentState = Lifecycle.State.CREATED
    }

    fun onAppear() {
        lifecycleRegistry.currentState = Lifecycle.State.STARTED
        lifecycleRegistry.currentState = Lifecycle.State.RESUMED
    }

    fun onDisappear() {
        lifecycleRegistry.currentState = Lifecycle.State.STARTED
        lifecycleRegistry.currentState = Lifecycle.State.CREATED
    }

    fun onDestroy(){
        lifecycleRegistry.currentState = Lifecycle.State.DESTROYED
    }

    override fun getLifecycle(): Lifecycle {
        return lifecycleRegistry
    }
}

所以问题是在哪里调用自定义 ViewHolder 的“onDestroy()”方法?

我是这样使用它的:

class Observer : LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    fun onCreate() {}

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    fun onDestroy() {}
}


class CountryViewHolder(
        private val mBinding: ItemCountryBinding,
        onCountryHeaderClicked: (Int, Boolean) -> Unit,
        onNearbyChallengeClicked: (Long?) -> Unit,
    ) : LifecycleViewHolder(mBinding.root){

        private var status = STATUS.COLLAPSED
        private var layoutStatus = HEIGHT.PENDING

        private val viewHolderObserver = Observer()
        private val challengesForCountryObserver = Observer<PagingData<ChallengeFullData>> {
            lifecycle.coroutineScope.launch {
                (mBinding.itemCountryChallengeList.adapter as ChallengesByCountryAdapter).submitData(it)
            }
        }

        init {
            lifecycle.addObserver(viewHolderObserver)
        }

        fun bind(data: TheCounterForCountryRel?, positionExpandedCountry: Int, viewModel: WeakReference<ViewModel>){
            val resources = itemView.context.resources

            if(data == null){
                mBinding.apply {
                    itemCountryIconExpand.rotation = 0F
                    itemCountryLabelChallengesQtd.text = resources.getString(R.string.item_country_challenges_qtd_placeholder)
                    itemCountryLabelName.text = resources.getString(R.string.item_country_label_name_placeholder)
                    

                    ... omitted for simplification ...

                    Picasso.get()
                        .load("")
                        .into(itemCountryPictureFlag)
                }
            }else{
                viewModel.get()?.getLiveDataForCountry(data.country.id)
                    ?.observe(this, challengesForCountryObserver)

                .... omitted for simplification ...
            }
        }
    }

这是我的 repo 你可以看到我是怎么做的 it.first 你必须将 parentLifecycleOwner 传递给适配器然后在 init 块中你必须观察 viewholder 的生命周期。

init {
    lifecycle.lifecycle.addObserver(object : LifecycleObserver {
        @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
        fun onDestroy() {
            recyclerView?.let { parent ->
                val childCount = parent.childCount
                for (i in 0 until childCount) {
                    parent.getChildAt(i)?.let {
                        (parent.getChildViewHolder(it) as MyViewHolder)
                            .run {
                                onDestroy()
                            }
                    }
                }
            }

        }

        @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
        fun onStop() {
            recyclerView?.let { parent ->
                val childCount = parent.childCount
                for (i in 0 until childCount) {
                    parent.getChildAt(i)?.let {
                        (parent.getChildViewHolder(it) as MyViewHolder)
                            .run {
                                onStop()
                            }
                    }
                }
            }
        }


        @OnLifecycleEvent(Lifecycle.Event.ON_START)
        fun onStart() {
            recyclerView?.run {
                if (layoutManager is LinearLayoutManager) {
                    val first =
                        (layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
                    val last =
                        (layoutManager as LinearLayoutManager).findLastVisibleItemPosition()
                    if (first in 0..last)
                        for (i in first..last) {
                            findViewHolderForAdapterPosition(i)?.let {
                                (it as MyViewHolder).onStart()
                            }
                        }
                }
            }
        }
    })

}

https://github.com/abhinavjiit/baseRecyclerview/blob/master/app/src/main/java/com/example/pristencare/adapter/RecyclerViewImageAdapter.kt