diff --git a/hooks/src/main/kotlin/xyz/junerver/compose/hooks/useBackFront.kt b/hooks/src/main/kotlin/xyz/junerver/compose/hooks/useBackFront.kt new file mode 100644 index 00000000..e1b67b91 --- /dev/null +++ b/hooks/src/main/kotlin/xyz/junerver/compose/hooks/useBackFront.kt @@ -0,0 +1,55 @@ +package xyz.junerver.compose.hooks + +import android.annotation.SuppressLint +import androidx.compose.runtime.Composable +import androidx.lifecycle.compose.LifecycleResumeEffect + +/** + * Description: 进入后台**再次**回到前台时执行Effect,不同于官方 API,只在再进入时才执行。 第一次渲染(不执行)-> + * 进入后台在返回(执行)。 + * + * Effect is executed when entering the background and returning to the + * foreground. Different from the official API, it is only executed when + * re-entering. + * + * First rendering (not executed) -> enter the background and return + * (executed) + * + * @author Junerver date: 2024/3/14-15:10 Email: junerver@gmail.com + * Version: v1.0 + */ +@SuppressLint("ComposableNaming") +@Composable +fun useBackToFrontEffect(vararg deps: Any?, effect: () -> Unit) { + val inBackgroundRef = useRef(default = false) + LifecycleResumeEffect(keys = deps) { + if (inBackgroundRef.current) { + effect() + inBackgroundRef.current = false + } + onPauseOrDispose { inBackgroundRef.current = true } + } +} + +/** + * Use front to back effect,contrary to the [useBackToFrontEffect] + * behavior, the effect is executed when the App enters the background + * + * @param deps + * @param effect + * @receiver + */ +@SuppressLint("ComposableNaming") +@Composable +fun useFrontToBackEffect(vararg deps: Any?, effect: () -> Unit) { + val inBackgroundRef = useRef(default = false) + LifecycleResumeEffect(keys = deps) { + if (inBackgroundRef.current) { + inBackgroundRef.current = false + } + onPauseOrDispose { + effect() + inBackgroundRef.current = true + } + } +} diff --git a/hooks/src/main/kotlin/xyz/junerver/compose/hooks/userequest/plugins/usePollingPlugin.kt b/hooks/src/main/kotlin/xyz/junerver/compose/hooks/userequest/plugins/usePollingPlugin.kt index 1099d799..3903e235 100644 --- a/hooks/src/main/kotlin/xyz/junerver/compose/hooks/userequest/plugins/usePollingPlugin.kt +++ b/hooks/src/main/kotlin/xyz/junerver/compose/hooks/userequest/plugins/usePollingPlugin.kt @@ -2,7 +2,6 @@ package xyz.junerver.compose.hooks.userequest.plugins import androidx.compose.runtime.Composable import androidx.compose.runtime.remember -import androidx.lifecycle.compose.LifecycleResumeEffect import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -10,6 +9,8 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.launch import xyz.junerver.compose.hooks.TParams +import xyz.junerver.compose.hooks.useBackToFrontEffect +import xyz.junerver.compose.hooks.useFrontToBackEffect import xyz.junerver.compose.hooks.userequest.Fetch import xyz.junerver.compose.hooks.userequest.GenPluginLifecycleFn import xyz.junerver.compose.hooks.userequest.OnBeforeReturn @@ -30,7 +31,7 @@ class PollingPlugin : Plugin() { // 已经重试计数 var currentRetryCount = 0 - var isBackground = false + var inBackground = false // 保存正在轮询的job,其本质是一个延时执行刷新的协程job private lateinit var pollingJob: Job @@ -82,7 +83,7 @@ class PollingPlugin : Plugin() { override val onFinally: ((params: TParams, data: TData?, e: Throwable?) -> Unit) get() = onFinally@{ _, _, _ -> usedScope = if (pollingWhenHidden) pluginScope else fetch.scope - if (!pollingWhenHidden && isBackground) return@onFinally + if (!pollingWhenHidden && inBackground) return@onFinally if (pollingErrorRetryCount == -1 || currentRetryCount <= pollingErrorRetryCount) { usedScope.launch(Dispatchers.IO) { delay(pollingInterval) @@ -119,17 +120,13 @@ fun usePollingPlugin(options: RequestOptions): Plugin { PollingPlugin() } if (!options.pollingWhenHidden) { - LifecycleResumeEffect(Unit) { - // resume时触发 - if (pollingPlugin.isBackground) { - pollingPlugin.refresh() - pollingPlugin.isBackground = false - } - onPauseOrDispose { - // 后台时暂停 - pollingPlugin.stopPolling(true) - pollingPlugin.isBackground = true - } + useBackToFrontEffect { + pollingPlugin.refresh() + pollingPlugin.inBackground = false + } + useFrontToBackEffect { + pollingPlugin.stopPolling(true) + pollingPlugin.inBackground = true } }