From cb5d517da0f6d742d34c456d1af1feb190e0e6f2 Mon Sep 17 00:00:00 2001 From: Osten <11805592+LagradOst@users.noreply.github.com> Date: Wed, 29 Apr 2026 22:28:32 +0200 Subject: [PATCH] fixed observe, aka #2567 --- .../lagradost/cloudstream3/mvvm/Lifecycle.kt | 62 +++++++++++++++++-- .../cloudstream3/ui/home/HomeFragment.kt | 1 - .../ui/home/HomeParentItemAdapterPreview.kt | 10 ++- .../ui/settings/testing/TestFragment.kt | 2 +- 4 files changed, 62 insertions(+), 13 deletions(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/mvvm/Lifecycle.kt b/app/src/main/java/com/lagradost/cloudstream3/mvvm/Lifecycle.kt index 3df5197cd..482ec05fc 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/mvvm/Lifecycle.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/mvvm/Lifecycle.kt @@ -1,16 +1,68 @@ package com.lagradost.cloudstream3.mvvm +import android.view.View +import androidx.activity.ComponentActivity +import androidx.core.view.doOnAttach import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LiveData +import androidx.lifecycle.findViewTreeLifecycleOwner +import androidx.viewbinding.ViewBinding +import com.lagradost.cloudstream3.ui.BaseFragment /** NOTE: Only one observer at a time per value */ -fun LifecycleOwner.observe(liveData: LiveData, action: (t: T) -> Unit) { - liveData.removeObservers(this) - liveData.observe(this) { it?.let { t -> action(t) } } +fun ComponentActivity.observe(liveData: LiveData, action: (T) -> Unit) { + observeNullable(liveData) { t -> t?.run(action) } } /** NOTE: Only one observer at a time per value */ -fun LifecycleOwner.observeNullable(liveData: LiveData, action: (t: T) -> Unit) { +fun ComponentActivity.observeNullable(liveData: LiveData, action: (T?) -> Unit) { liveData.removeObservers(this) - liveData.observe(this) { action(it) } + liveData.observe(this, action) } + +/** NOTE: Only one observer at a time per value */ +fun BaseFragment.observe(liveData: LiveData, action: (T) -> Unit) { + observeNullable(liveData) { t -> t?.run(action) } +} + +/** + * Attaches an observable to the root binding, instead of the fragment. This is more efficient as + * it will not call observe if the view is in the background. + * + * NOTE: Only one observer at a time per value + * */ +fun BaseFragment.observeNullable( + liveData: LiveData, action: (T?) -> Unit +) { + val root = this.binding?.root + if (root == null) { + liveData.removeObservers(this) + liveData.observe(this, action) + } else { + root.doOnAttach { view -> + // On attach should make findViewTreeLifecycleOwner non-null, but use "this" just in case + val owner: LifecycleOwner = view.findViewTreeLifecycleOwner() ?: this@observeNullable + liveData.removeObservers(owner) + liveData.observe(owner, action) + } + } +} + +/** NOTE: Only one observer at a time per value */ +fun View.observe(liveData: LiveData, action: (T) -> Unit) { + observeNullable(liveData) { t -> t?.run(action) } +} + +/** NOTE: Only one observer at a time per value */ +fun View.observeNullable(liveData: LiveData, action: (T?) -> Unit) { + doOnAttach { view -> + // On attach should make findViewTreeLifecycleOwner non-null + val owner: LifecycleOwner? = view.findViewTreeLifecycleOwner() + if(owner == null) { + debugException { "Expected non-null findViewTreeLifecycleOwner" } + return@doOnAttach + } + liveData.removeObservers(owner) + liveData.observe(owner, action) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt index 375b2313f..b68ef5962 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeFragment.kt @@ -651,7 +651,6 @@ class HomeFragment : BaseFragment( } homeMasterAdapter = HomeParentItemAdapterPreview( - fragment = this@HomeFragment, homeViewModel, accountViewModel ) homeMasterRecycler.setRecycledViewPool(ParentItemAdapter.sharedPool) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeParentItemAdapterPreview.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeParentItemAdapterPreview.kt index a292c2da2..959806e56 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeParentItemAdapterPreview.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeParentItemAdapterPreview.kt @@ -63,7 +63,6 @@ import androidx.core.graphics.toColorInt import com.lagradost.cloudstream3.ui.setRecycledViewPool class HomeParentItemAdapterPreview( - val fragment: LifecycleOwner, private val viewModel: HomeViewModel, private val accountViewModel: AccountViewModel ) : ParentItemAdapter( @@ -105,7 +104,7 @@ class HomeParentItemAdapterPreview( ) } - return HeaderViewHolder(binding, viewModel, accountViewModel, fragment) + return HeaderViewHolder(binding, viewModel, accountViewModel) } override fun onBindHeader(holder: ViewHolderState) { @@ -132,7 +131,6 @@ class HomeParentItemAdapterPreview( val binding: ViewBinding, val viewModel: HomeViewModel, accountViewModel: AccountViewModel, - fragment: LifecycleOwner, ) : ViewHolderState(binding) { @@ -544,7 +542,7 @@ class HomeParentItemAdapterPreview( headProfilePicCard?.isGone = isLayout(TV or EMULATOR) alternateHeadProfilePicCard?.isGone = isLayout(TV or EMULATOR) - fragment.observe(viewModel.currentAccount) { currentAccount -> + (headProfilePic ?: alternateHeadProfilePic)?.observe(viewModel.currentAccount) { currentAccount -> headProfilePic?.loadImage(currentAccount?.image) alternateHeadProfilePic?.loadImage(currentAccount?.image) } @@ -775,7 +773,7 @@ class HomeParentItemAdapterPreview( fun onViewAttachedToWindow() { previewViewpager.registerOnPageChangeCallback(previewCallback) - binding.root.findViewTreeLifecycleOwner()?.apply { + previewViewpager.apply { observe(viewModel.preview) { updatePreview(it) } @@ -800,7 +798,7 @@ class HomeParentItemAdapterPreview( } toggleListHolder?.isGone = visible.isEmpty() } - } ?: debugException { "Expected findViewTreeLifecycleOwner" } + } } } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/testing/TestFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/testing/TestFragment.kt index 37677c1d8..4ec005a09 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/testing/TestFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/testing/TestFragment.kt @@ -40,7 +40,7 @@ class TestFragment : BaseFragment( providerTest.setProgress(passed, failed, total) } - observeNullable(testViewModel.providerResults) { + observe(testViewModel.providerResults) { safe { val newItems = it.sortedBy { api -> api.first.name } (providerTestRecyclerView.adapter as? TestResultAdapter)?.submitList(