|
|
@ -3,17 +3,12 @@ package com.github.apognu.otter.repositories |
|
|
|
import android.content.Context |
|
|
|
import android.content.Context |
|
|
|
import com.github.apognu.otter.utils.Cache |
|
|
|
import com.github.apognu.otter.utils.Cache |
|
|
|
import com.github.apognu.otter.utils.CacheItem |
|
|
|
import com.github.apognu.otter.utils.CacheItem |
|
|
|
import com.github.apognu.otter.utils.log |
|
|
|
|
|
|
|
import com.github.apognu.otter.utils.untilNetwork |
|
|
|
|
|
|
|
import com.google.gson.Gson |
|
|
|
|
|
|
|
import kotlinx.coroutines.Dispatchers.IO |
|
|
|
import kotlinx.coroutines.Dispatchers.IO |
|
|
|
import kotlinx.coroutines.GlobalScope |
|
|
|
import kotlinx.coroutines.flow.* |
|
|
|
import kotlinx.coroutines.channels.Channel |
|
|
|
|
|
|
|
import kotlinx.coroutines.launch |
|
|
|
|
|
|
|
import java.io.BufferedReader |
|
|
|
import java.io.BufferedReader |
|
|
|
|
|
|
|
|
|
|
|
interface Upstream<D> { |
|
|
|
interface Upstream<D> { |
|
|
|
fun fetch(size: Int = 0): Channel<Repository.Response<D>>? |
|
|
|
fun fetch(size: Int = 0): Flow<Repository.Response<D>> |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
abstract class Repository<D : Any, C : CacheItem<D>> { |
|
|
|
abstract class Repository<D : Any, C : CacheItem<D>> { |
|
|
@ -28,44 +23,29 @@ abstract class Repository<D : Any, C : CacheItem<D>> { |
|
|
|
abstract val cacheId: String? |
|
|
|
abstract val cacheId: String? |
|
|
|
abstract val upstream: Upstream<D> |
|
|
|
abstract val upstream: Upstream<D> |
|
|
|
|
|
|
|
|
|
|
|
private var _channel: Channel<Response<D>>? = null |
|
|
|
|
|
|
|
private val channel: Channel<Response<D>> |
|
|
|
|
|
|
|
get() { |
|
|
|
|
|
|
|
if (_channel?.isClosedForSend ?: true) { |
|
|
|
|
|
|
|
_channel = Channel(10) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return _channel!! |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
open fun cache(data: List<D>): C? = null |
|
|
|
open fun cache(data: List<D>): C? = null |
|
|
|
protected open fun uncache(reader: BufferedReader): C? = null |
|
|
|
protected open fun uncache(reader: BufferedReader): C? = null |
|
|
|
|
|
|
|
|
|
|
|
fun fetch(upstreams: Int = Origin.Cache.origin and Origin.Network.origin, size: Int = 0): Channel<Response<D>> { |
|
|
|
fun fetch(upstreams: Int = Origin.Cache.origin and Origin.Network.origin, size: Int = 0): Flow<Response<D>> = flow { |
|
|
|
if (Origin.Cache.origin and upstreams == upstreams) fromCache() |
|
|
|
if (Origin.Cache.origin and upstreams == upstreams) fromCache().collect { emit(it) } |
|
|
|
if (Origin.Network.origin and upstreams == upstreams) fromNetwork(size) |
|
|
|
if (Origin.Network.origin and upstreams == upstreams) fromNetwork(size).collect { emit(it) } |
|
|
|
|
|
|
|
|
|
|
|
return channel |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private fun fromCache() { |
|
|
|
private fun fromCache() = flow { |
|
|
|
GlobalScope.launch(IO) { |
|
|
|
cacheId?.let { cacheId -> |
|
|
|
cacheId?.let { cacheId -> |
|
|
|
Cache.get(context, cacheId)?.let { reader -> |
|
|
|
Cache.get(context, cacheId)?.let { reader -> |
|
|
|
uncache(reader)?.let { cache -> |
|
|
|
uncache(reader)?.let { cache -> |
|
|
|
emit(Response(Origin.Cache, cache.data, false)) |
|
|
|
channel.offer(Response(Origin.Cache, cache.data, false)) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
}.flowOn(IO) |
|
|
|
|
|
|
|
|
|
|
|
private fun fromNetwork(size: Int) { |
|
|
|
private fun fromNetwork(size: Int) = flow { |
|
|
|
upstream.fetch(size)?.untilNetwork(IO) { data, _, hasMore -> |
|
|
|
upstream |
|
|
|
val data = onDataFetched(data) |
|
|
|
.fetch(size) |
|
|
|
|
|
|
|
.map { response -> Response(Origin.Network, onDataFetched(response.data), response.hasMore) } |
|
|
|
channel.offer(Response(Origin.Network, data, hasMore)) |
|
|
|
.collect { response -> emit(Response(Origin.Network, response.data, response.hasMore)) } |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected open fun onDataFetched(data: List<D>) = data |
|
|
|
protected open fun onDataFetched(data: List<D>) = data |
|
|
|