Merge TAVRIDA-MR-5: Async load
This commit is contained in:
commit
d720470ea2
@ -1,6 +1,7 @@
|
||||
package centre.sciprog.maps.compose
|
||||
|
||||
import androidx.compose.ui.graphics.ImageBitmap
|
||||
import kotlinx.coroutines.Deferred
|
||||
import kotlin.math.floor
|
||||
|
||||
data class TileId(
|
||||
@ -15,7 +16,7 @@ data class MapTile(
|
||||
)
|
||||
|
||||
interface MapTileProvider {
|
||||
suspend fun loadTile(id: TileId): MapTile
|
||||
fun loadTileAsync(id: TileId): Deferred<MapTile>
|
||||
|
||||
val tileSize: Int get() = DEFAULT_TILE_SIZE
|
||||
|
||||
@ -26,4 +27,6 @@ interface MapTileProvider {
|
||||
companion object {
|
||||
const val DEFAULT_TILE_SIZE = 256
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun MapTileProvider.loadTile(id: TileId): MapTile = loadTileAsync(id).await()
|
@ -17,6 +17,7 @@ import androidx.compose.ui.graphics.toArgb
|
||||
import androidx.compose.ui.input.pointer.*
|
||||
import androidx.compose.ui.unit.*
|
||||
import centre.sciprog.maps.*
|
||||
import kotlinx.coroutines.launch
|
||||
import mu.KotlinLogging
|
||||
import org.jetbrains.skia.Font
|
||||
import org.jetbrains.skia.Paint
|
||||
@ -149,8 +150,10 @@ actual fun MapView(
|
||||
if (i in indexRange && j in indexRange) {
|
||||
val tileId = TileId(zoom, i, j)
|
||||
try {
|
||||
val tile = mapTileProvider.loadTile(tileId)
|
||||
mapTiles.add(tile)
|
||||
launch {
|
||||
val tile = mapTileProvider.loadTileAsync(tileId)
|
||||
mapTiles.add(tile.await())
|
||||
}
|
||||
} catch (ex: Exception) {
|
||||
logger.error(ex) { "Failed to load tile $tileId" }
|
||||
}
|
||||
|
@ -5,7 +5,10 @@ import androidx.compose.ui.graphics.toComposeImageBitmap
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.statement.readBytes
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Deferred
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.async
|
||||
import mu.KotlinLogging
|
||||
import org.jetbrains.skia.Image
|
||||
import java.net.URL
|
||||
@ -16,7 +19,11 @@ import kotlin.math.pow
|
||||
/**
|
||||
* A [MapTileProvider] based on Open Street Map API. With in-memory and file cache
|
||||
*/
|
||||
public class OpenStreetMapTileProvider(private val scope: CoroutineScope, private val client: HttpClient, private val cacheDirectory: Path): MapTileProvider {
|
||||
public class OpenStreetMapTileProvider(
|
||||
private val scope: CoroutineScope,
|
||||
private val client: HttpClient,
|
||||
private val cacheDirectory: Path,
|
||||
) : MapTileProvider {
|
||||
private val cache = HashMap<TileId, Deferred<ImageBitmap>>()
|
||||
|
||||
private fun TileId.osmUrl() = URL("https://tile.openstreetmap.org/${zoom}/${i}/${j}.png")
|
||||
@ -53,20 +60,22 @@ public class OpenStreetMapTileProvider(private val scope: CoroutineScope, privat
|
||||
Image.makeFromEncoded(byteArray).toComposeImageBitmap()
|
||||
}
|
||||
|
||||
override suspend fun loadTile(id: TileId): MapTile {
|
||||
override fun loadTileAsync(id: TileId): Deferred<MapTile> {
|
||||
val indexRange = indexRange(id.zoom)
|
||||
if(id.i !in indexRange || id.j !in indexRange){
|
||||
if (id.i !in indexRange || id.j !in indexRange) {
|
||||
error("Indices (${id.i}, ${id.j}) are not in index range $indexRange for zoom ${id.zoom}")
|
||||
}
|
||||
|
||||
val image = cache.getOrPut(id) {
|
||||
downloadImageAsync(id)
|
||||
}.await()
|
||||
}
|
||||
|
||||
return MapTile(id, image)
|
||||
return scope.async {
|
||||
MapTile(id, image.await())
|
||||
}
|
||||
}
|
||||
|
||||
companion object{
|
||||
companion object {
|
||||
private val logger = KotlinLogging.logger("OpenStreetMapCache")
|
||||
private fun indexRange(zoom: Int): IntRange = 0 until 2.0.pow(zoom).toInt()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user