Skip to content

Commit

Permalink
Merge pull request #137 from soil-kt/actor-simplify
Browse files Browse the repository at this point in the history
Simplify the Internal Lifecycle of Actor
  • Loading branch information
ogaclejapan authored Nov 30, 2024
2 parents 94d8190 + dad16b3 commit 30d4461
Show file tree
Hide file tree
Showing 26 changed files with 383 additions and 358 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
package soil.query.compose

import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import soil.query.InfiniteQueryKey
import soil.query.InfiniteQueryRef
import soil.query.QueryChunks
import soil.query.QueryClient
import soil.query.compose.internal.newInfiniteQuery
Expand All @@ -29,6 +31,7 @@ fun <T, S> rememberInfiniteQuery(
): InfiniteQueryObject<QueryChunks<T, S>, S> {
val scope = rememberCoroutineScope()
val query = remember(key.id) { newInfiniteQuery(key, config, client, scope) }
query.Effect()
return with(config.mapper) {
config.strategy.collectAsState(query).toObject(query = query, select = { it })
}
Expand All @@ -54,7 +57,19 @@ fun <T, S, U> rememberInfiniteQuery(
): InfiniteQueryObject<U, S> {
val scope = rememberCoroutineScope()
val query = remember(key.id) { newInfiniteQuery(key, config, client, scope) }
query.Effect()
return with(config.mapper) {
config.strategy.collectAsState(query).toObject(query = query, select = select)
}
}

@Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress")
@Composable
private inline fun InfiniteQueryRef<*, *>.Effect() {
// TODO: Switch to LifecycleResumeEffect
// Android, it works only with Compose UI 1.7.0-alpha05 or above.
// Therefore, we will postpone adding this code until a future release.
LaunchedEffect(id) {
join()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
package soil.query.compose

import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import soil.query.QueryClient
import soil.query.QueryKey
import soil.query.QueryRef
import soil.query.compose.internal.newCombinedQuery
import soil.query.compose.internal.newQuery

Expand All @@ -28,6 +30,7 @@ fun <T> rememberQuery(
): QueryObject<T> {
val scope = rememberCoroutineScope()
val query = remember(key.id) { newQuery(key, config, client, scope) }
query.Effect()
return with(config.mapper) {
config.strategy.collectAsState(query).toObject(query = query, select = { it })
}
Expand All @@ -53,6 +56,7 @@ fun <T, U> rememberQuery(
): QueryObject<U> {
val scope = rememberCoroutineScope()
val query = remember(key.id) { newQuery(key, config, client, scope) }
query.Effect()
return with(config.mapper) {
config.strategy.collectAsState(query).toObject(query = query, select = select)
}
Expand Down Expand Up @@ -83,6 +87,7 @@ fun <T1, T2, R> rememberQuery(
val query = remember(key1.id, key2.id) {
newCombinedQuery(key1, key2, transform, config, client, scope)
}
query.Effect()
return with(config.mapper) {
config.strategy.collectAsState(query).toObject(query = query, select = { it })
}
Expand Down Expand Up @@ -116,6 +121,7 @@ fun <T1, T2, T3, R> rememberQuery(
val query = remember(key1.id, key2.id, key3.id) {
newCombinedQuery(key1, key2, key3, transform, config, client, scope)
}
query.Effect()
return with(config.mapper) {
config.strategy.collectAsState(query).toObject(query = query, select = { it })
}
Expand Down Expand Up @@ -143,7 +149,19 @@ fun <T, R> rememberQuery(
val query = remember(*keys.map { it.id }.toTypedArray()) {
newCombinedQuery(keys, transform, config, client, scope)
}
query.Effect()
return with(config.mapper) {
config.strategy.collectAsState(query).toObject(query = query, select = { it })
}
}

@Suppress("NOTHING_TO_INLINE", "KotlinRedundantDiagnosticSuppress")
@Composable
private inline fun QueryRef<*>.Effect() {
// TODO: Switch to LifecycleResumeEffect
// Android, it works only with Compose UI 1.7.0-alpha05 or above.
// Therefore, we will postpone adding this code until a future release.
LaunchedEffect(id) {
join()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch
import soil.query.QueryClient
import soil.query.QueryId
Expand Down Expand Up @@ -53,6 +54,11 @@ private class CombinedQuery2<T1, T2, R>(
)
override val state: StateFlow<QueryState<R>> = _state

override fun close() {
query1.close()
query2.close()
}

override suspend fun resume() {
coroutineScope {
val deferred1 = async { query1.resume() }
Expand All @@ -69,9 +75,11 @@ private class CombinedQuery2<T1, T2, R>(
}
}

override fun launchIn(scope: CoroutineScope): Job {
return scope.launch {
combine(query1.state, query2.state, ::merge).collect { _state.value = it }
override suspend fun join() {
coroutineScope {
val job1 = launch { query1.join() }
val job2 = launch { query2.join() }
joinAll(job1, job2)
}
}

Expand All @@ -80,26 +88,23 @@ private class CombinedQuery2<T1, T2, R>(
}

// ----- RememberObserver -----//
private var jobs: List<Job>? = null
private var job: Job? = null

override fun onAbandoned() = stop()

override fun onForgotten() = stop()

override fun onRemembered() {
stop()
start()
}
override fun onRemembered() = start()

private fun start() {
val job1 = query1.launchIn(scope)
val job2 = query2.launchIn(scope)
val job3 = launchIn(scope)
jobs = listOf(job1, job2, job3)
job = scope.launch {
combine(query1.state, query2.state, ::merge).collect { _state.value = it }
}
}

private fun stop() {
jobs?.forEach { it.cancel() }
jobs = null
job?.cancel()
job = null
close()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch
import soil.query.QueryClient
import soil.query.QueryId
Expand Down Expand Up @@ -56,6 +57,12 @@ private class CombinedQuery3<T1, T2, T3, R>(
)
override val state: StateFlow<QueryState<R>> = _state

override fun close() {
query1.close()
query2.close()
query3.close()
}

override suspend fun resume() {
coroutineScope {
val deferred1 = async { query1.resume() }
Expand All @@ -74,9 +81,12 @@ private class CombinedQuery3<T1, T2, T3, R>(
}
}

override fun launchIn(scope: CoroutineScope): Job {
return scope.launch {
combine(query1.state, query2.state, query3.state, ::merge).collect { _state.value = it }
override suspend fun join() {
coroutineScope {
val job1 = launch { query1.join() }
val job2 = launch { query2.join() }
val job3 = launch { query3.join() }
joinAll(job1, job2, job3)
}
}

Expand All @@ -85,27 +95,23 @@ private class CombinedQuery3<T1, T2, T3, R>(
}

// ----- RememberObserver -----//
private var jobs: List<Job>? = null
private var job: Job? = null

override fun onAbandoned() = stop()

override fun onForgotten() = stop()

override fun onRemembered() {
stop()
start()
}
override fun onRemembered() = start()

private fun start() {
val job1 = query1.launchIn(scope)
val job2 = query2.launchIn(scope)
val job3 = query3.launchIn(scope)
val job4 = launchIn(scope)
jobs = listOf(job1, job2, job3, job4)
job = scope.launch {
combine(query1.state, query2.state, query3.state, ::merge).collect { _state.value = it }
}
}

private fun stop() {
jobs?.forEach { it.cancel() }
jobs = null
job?.cancel()
job = null
close()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch
import soil.query.QueryClient
import soil.query.QueryId
Expand Down Expand Up @@ -49,6 +50,10 @@ private class CombinedQueryN<T, R>(
)
override val state: StateFlow<QueryState<R>> = _state

override fun close() {
queries.forEach { it.close() }
}

override suspend fun resume() {
coroutineScope {
queries.map { query -> async { query.resume() } }.awaitAll()
Expand All @@ -61,9 +66,9 @@ private class CombinedQueryN<T, R>(
}
}

override fun launchIn(scope: CoroutineScope): Job {
return scope.launch {
combine(queries.map { it.state }, ::merge).collect { _state.value = it }
override suspend fun join() {
coroutineScope {
queries.map { query -> launch { query.join() } }.joinAll()
}
}

Expand All @@ -72,23 +77,23 @@ private class CombinedQueryN<T, R>(
}

// ----- RememberObserver -----//
private var jobs: List<Job>? = null
private var job: Job? = null

override fun onAbandoned() = stop()

override fun onForgotten() = stop()

override fun onRemembered() {
stop()
start()
}
override fun onRemembered() = start()

private fun start() {
jobs = queries.map { it.launchIn(scope) } + launchIn(scope)
job = scope.launch {
combine(queries.map { it.state }, ::merge).collect { _state.value = it }
}
}

private fun stop() {
jobs?.forEach { it.cancel() }
jobs = null
job?.cancel()
job = null
close()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ private class InfiniteQuery<T, S>(
)
override val state: StateFlow<QueryState<QueryChunks<T, S>>> = _state

override fun close() = query.close()

override fun nextParam(data: QueryChunks<T, S>): S? = query.nextParam(data)

override suspend fun resume() = query.resume()
Expand All @@ -49,32 +51,26 @@ private class InfiniteQuery<T, S>(

override suspend fun invalidate() = query.invalidate()

override fun launchIn(scope: CoroutineScope): Job {
return scope.launch {
query.state.collect { _state.value = optimize(it) }
}
}
override suspend fun join() = query.join()

// ----- RememberObserver -----//
private var jobs: List<Job>? = null
private var job: Job? = null

override fun onAbandoned() = stop()

override fun onForgotten() = stop()

override fun onRemembered() {
stop()
start()
}
override fun onRemembered() = start()

private fun start() {
val job1 = query.launchIn(scope)
val job2 = launchIn(scope)
jobs = listOf(job1, job2)
job = scope.launch {
query.state.collect { _state.value = optimize(it) }
}
}

private fun stop() {
jobs?.forEach { it.cancel() }
jobs = null
job?.cancel()
job = null
close()
}
}
Loading

0 comments on commit 30d4461

Please sign in to comment.