From 30d6fd9d33e17110726a299749b058416ed77ecf Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Tue, 23 Nov 2021 11:46:10 -0800 Subject: Convert fragment channel to flow --- .../frost/activities/BaseMainActivity.kt | 19 ++++++++-------- .../pitchedapps/frost/activities/MainActivity.kt | 12 +++++++---- .../frost/contracts/ActivityContract.kt | 3 ++- .../pitchedapps/frost/fragments/BaseFragment.kt | 25 ++++++++-------------- .../frost/fragments/FragmentContract.kt | 10 +-------- 5 files changed, 30 insertions(+), 39 deletions(-) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt index 84352cb4..8585f68b 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseMainActivity.kt @@ -498,7 +498,10 @@ abstract class BaseMainActivity : ) positiveButton(R.string.kau_yes) { this@BaseMainActivity.launch { - fbCookie.logout(this@BaseMainActivity, deleteCookie = true) + fbCookie.logout( + this@BaseMainActivity, + deleteCookie = true + ) } } negativeButton(R.string.kau_no) @@ -637,7 +640,7 @@ abstract class BaseMainActivity : private fun refreshAll() { L.d { "Refresh all" } - fragmentChannel.offer(REQUEST_REFRESH) + fragmentEmit(REQUEST_REFRESH) } override fun onCreateOptionsMenu(menu: Menu): Boolean { @@ -737,19 +740,19 @@ abstract class BaseMainActivity : * These results can be stacked */ if (hasRequest(REQUEST_REFRESH)) { - fragmentChannel.offer(REQUEST_REFRESH) + fragmentEmit(REQUEST_REFRESH) } if (hasRequest(REQUEST_NAV)) { frostNavigationBar(prefs, themeProvider) } if (hasRequest(REQUEST_TEXT_ZOOM)) { - fragmentChannel.offer(REQUEST_TEXT_ZOOM) + fragmentEmit(REQUEST_TEXT_ZOOM) } if (hasRequest(REQUEST_SEARCH)) { invalidateOptionsMenu() } if (hasRequest(REQUEST_FAB)) { - fragmentChannel.offer(lastPosition) + fragmentEmit(lastPosition) } if (hasRequest(REQUEST_NOTIFICATION)) { scheduleNotificationsFromPrefs(prefs) @@ -792,7 +795,6 @@ abstract class BaseMainActivity : override fun onDestroy() { controlWebview?.destroy() super.onDestroy() - fragmentChannel.close() } override fun collapseAppBar() { @@ -864,10 +866,9 @@ abstract class BaseMainActivity : lastPosition = 0 viewpager.setCurrentItem(0, false) viewpager.offscreenPageLimit = pages.size + // todo check if post is necessary viewpager.post { - if (!fragmentChannel.isClosedForSend) { - fragmentChannel.offer(0) - } + fragmentEmit(0) } // trigger hook so title is set } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt index 4b18088c..97067b21 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt @@ -27,6 +27,8 @@ import com.pitchedapps.frost.web.FrostEmitter import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.channels.BroadcastChannel +import kotlinx.coroutines.channels.BufferOverflow +import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow @@ -39,8 +41,10 @@ import kotlinx.coroutines.flow.onEach @UseExperimental(ExperimentalCoroutinesApi::class) class MainActivity : BaseMainActivity() { - - override val fragmentChannel = BroadcastChannel(10) + + private val fragmentMutableFlow = MutableSharedFlow(extraBufferCapacity = 10, onBufferOverflow = BufferOverflow.DROP_OLDEST) + override val fragmentFlow: SharedFlow = fragmentMutableFlow.asSharedFlow() + override val fragmentEmit: FrostEmitter = FrostEmitter { fragmentMutableFlow.tryEmit(it) } private val headerMutableFlow = MutableStateFlow("") override val headerFlow: SharedFlow = headerMutableFlow.asSharedFlow() @@ -61,9 +65,9 @@ class MainActivity : BaseMainActivity() { return } if (lastPosition != -1) { - fragmentChannel.offer(-(lastPosition + 1)) + fragmentEmit(-(lastPosition + 1)) } - fragmentChannel.offer(position) + fragmentEmit(position) lastPosition = position } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/contracts/ActivityContract.kt b/app/src/main/kotlin/com/pitchedapps/frost/contracts/ActivityContract.kt index 83110417..3c5d7412 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/contracts/ActivityContract.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/contracts/ActivityContract.kt @@ -25,7 +25,8 @@ import kotlinx.coroutines.flow.SharedFlow @UseExperimental(ExperimentalCoroutinesApi::class) interface MainActivityContract : MainFabContract { - val fragmentChannel: BroadcastChannel + val fragmentFlow: SharedFlow + val fragmentEmit: FrostEmitter val headerFlow: SharedFlow val headerEmit: FrostEmitter diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/BaseFragment.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/BaseFragment.kt index 79495b2a..5c97de65 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/BaseFragment.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/BaseFragment.kt @@ -21,6 +21,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment +import androidx.lifecycle.flowWithLifecycle import ca.allanwang.kau.utils.ContextHelper import ca.allanwang.kau.utils.fadeScaleTransition import ca.allanwang.kau.utils.setIcon @@ -47,8 +48,9 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.Job import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.channels.ReceiveChannel +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.isActive -import kotlinx.coroutines.launch import javax.inject.Inject import kotlin.coroutines.CoroutineContext @@ -121,7 +123,6 @@ abstract class BaseFragment : } override var firstLoad: Boolean = true - private var activityReceiver: ReceiveChannel? = null private var onCreateRunnable: ((FragmentContract) -> Unit)? = null override var content: FrostContentParent? = null @@ -152,8 +153,7 @@ abstract class BaseFragment : onCreateRunnable?.invoke(this) onCreateRunnable = null firstLoadRequest() - detachMainObservable() - activityReceiver = attachMainObservable(mainContract) + attach(mainContract) } override fun setUserVisibleHint(isVisibleToUser: Boolean) { @@ -177,10 +177,10 @@ abstract class BaseFragment : mainContract.setTitle(title) } - override fun attachMainObservable(contract: MainActivityContract): ReceiveChannel { - val receiver = contract.fragmentChannel.openSubscription() - launch { - for (flag in receiver) { + override fun attach(contract: MainActivityContract) { + contract.fragmentFlow + .flowWithLifecycle(viewLifecycleOwner.lifecycle) + .onEach { flag -> when (flag) { REQUEST_REFRESH -> { core?.apply { @@ -201,9 +201,7 @@ abstract class BaseFragment : reloadTextSize() } } - } - } - return receiver + }.launchIn(this) } override fun updateFab(contract: MainFabContract) { @@ -222,16 +220,11 @@ abstract class BaseFragment : setOnClickListener { click() } } - override fun detachMainObservable() { - activityReceiver?.cancel() - } - override fun onDestroyView() { super.onDestroyView() L.i { "Fragment on destroy $position ${hashCode()}" } content?.destroy() content = null - detachMainObservable() } override fun onDestroy() { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentContract.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentContract.kt index 10c612c5..beac7494 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentContract.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/FragmentContract.kt @@ -22,7 +22,6 @@ import com.pitchedapps.frost.contracts.FrostContentParent import com.pitchedapps.frost.contracts.MainActivityContract import com.pitchedapps.frost.contracts.MainFabContract import com.pitchedapps.frost.views.FrostRecyclerView -import kotlinx.coroutines.channels.ReceiveChannel /** * Created by Allan Wang on 2017-11-07. @@ -77,15 +76,8 @@ interface FragmentContract : FrostContentContainer { /** * Call whenever a fragment is attached so that it may listen * to activity emissions. - * Returns a means of closing the listener, which can be called from [detachMainObservable] */ - fun attachMainObservable(contract: MainActivityContract): ReceiveChannel - - /** - * Call when fragment is detached so that any existing - * observable is disposed - */ - fun detachMainObservable() + fun attach(contract: MainActivityContract) /* * ----------------------------------------- -- cgit v1.2.3