如何在 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()
}
}
}
}
}
})
}
我需要从 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()
}
}
}
}
}
})
}