Created
October 8, 2021 13:26
-
-
Save almozavr/28bbca9452dd5933eae4f35848ce84e4 to your computer and use it in GitHub Desktop.
Link ContainerHost intent capabilities with the Paging library
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.paging | |
import androidx.paging.PagingSource | |
import androidx.paging.PagingState | |
import org.orbitmvi.orbit.ContainerHost | |
import org.orbitmvi.orbit.syntax.simple.SimpleSyntax | |
import org.orbitmvi.orbit.syntax.simple.intent | |
import kotlin.coroutines.resume | |
import kotlin.coroutines.resumeWithException | |
import kotlin.coroutines.suspendCoroutine | |
/** | |
* Proxy [PagingSource] that delegates calls to the actual source | |
* which is created at the moment of load. The calls are delegated only if actual source creation succeeds. | |
*/ | |
class DelegatingPagingSource<K : Any, V : Any>( | |
private val producer: PagingSourceProducer<K, V> | |
) : PagingSource<K, V>() { | |
private var actualSource: PagingSource<K, V>? = null | |
override fun getRefreshKey(state: PagingState<K, V>): K? = | |
actualSource?.getRefreshKey(state) | |
override suspend fun load(params: LoadParams<K>): LoadResult<K, V> { | |
if (actualSource == null) { | |
actualSource = producer.invoke(params) | |
} | |
return actualSource?.load(params) ?: LoadResult.Error(IllegalStateException("Can't create actual source")) | |
} | |
companion object { | |
fun <K : Any, V : Any> create(producer: PagingSourceProducer<K, V>) = DelegatingPagingSource(producer) | |
} | |
} | |
private typealias PagingSourceProducer<K, V> = suspend (PagingSource.LoadParams<K>) -> PagingSource<K, V>? | |
/** | |
* Create [DelegatingPagingSource] with [producer] wrapped in the [ContainerHost.intent] call | |
*/ | |
fun <S : Any, E : Any, K : Any, V : Any> ContainerHost<S, E>.createPagingSource( | |
producer: ContainerPagingSourceProducer<S, E, K, V> | |
) = | |
DelegatingPagingSource.create<K, V> { params -> | |
return@create suspendCoroutine { continuation -> | |
intent { | |
try { | |
val pagingSource = producer(this, params) | |
continuation.resume(pagingSource) | |
} catch (e: Exception) { | |
continuation.resumeWithException(e) | |
} | |
} | |
} | |
} | |
private typealias ContainerPagingSourceProducer<S, E, K, V> = | |
suspend SimpleSyntax<S, E>.(params: PagingSource.LoadParams<K>) -> PagingSource<K, V>? |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.myitems | |
import androidx.lifecycle.SavedStateHandle | |
import androidx.lifecycle.ViewModel | |
import androidx.lifecycle.viewModelScope | |
import androidx.paging.Pager | |
import androidx.paging.PagingConfig | |
import androidx.paging.PagingData | |
import androidx.paging.PagingSource | |
import androidx.paging.PagingState | |
import androidx.paging.cachedIn | |
import androidx.paging.map | |
import com.example.paging.createPagingSource | |
import kotlinx.coroutines.flow.Flow | |
import kotlinx.coroutines.flow.collect | |
import kotlinx.coroutines.flow.map | |
import kotlinx.coroutines.flow.onEach | |
import org.orbitmvi.orbit.Container | |
import org.orbitmvi.orbit.ContainerHost | |
import org.orbitmvi.orbit.syntax.simple.intent | |
import org.orbitmvi.orbit.syntax.simple.postSideEffect | |
import org.orbitmvi.orbit.syntax.simple.reduce | |
import org.orbitmvi.orbit.viewmodel.container | |
class MyItemsViewModel( | |
savedStateHandle: SavedStateHandle, | |
exceptionHandler: ExceptionHandler, | |
private val getMyValuableDataUseCase: GetMyValuableDataUseCase, | |
) : ViewModel(), ContainerHost<MyItemsState, MyItemsEffect> { | |
override val container: Container<MyItemsState, MyItemsEffect> = container( | |
initialState = MyItemsState( | |
myValuableData = null, | |
), | |
savedStateHandle = savedStateHandle, | |
) | |
val myItems: Flow<PagingData<MyItem>> = Pager( | |
config = PagingConfig( | |
pageSize = 10, | |
enablePlaceholders = false, | |
) | |
) { | |
createMyItemPagingSource() | |
}.flow.map { pagingData -> | |
pagingData.map { it.asPresentation() } | |
}.cachedIn(viewModelScope) | |
private fun createMyItemPagingSource(): PagingSource<Int, MyItem> = createPagingSource { | |
val valuableData = state.myValuableData | |
if (valuableData == null) { | |
val newValuableData = getMyValuableDataUseCase() | |
reduce { | |
state.copy(myValuableData = newValuableData) | |
} | |
return@createPagingSource createActualMyItemPagingSource(newValuableData) | |
} else { | |
return@createPagingSource createActualMyItemPagingSource(valuableData) | |
} | |
return@createPagingSource null | |
} | |
private fun createActualMyItemPagingSource(valuableData: ValuableData): PagingSource<Int, MyItem> = TODO() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment