Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shields loading optimization #6826

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,14 +1,34 @@
package com.mapbox.navigation.ui.shield

import com.mapbox.navigation.ui.shield.internal.RoadShieldDownloader
import com.mapbox.navigation.ui.shield.internal.loader.CachedResourceLoader
import com.mapbox.navigation.ui.shield.internal.loader.RoadShieldLoader
import com.mapbox.navigation.ui.shield.internal.loader.ShieldSpritesDownloader
import com.mapbox.navigation.ui.shield.internal.model.RouteShieldToDownload

/**
* Container for [RoadShieldContentManager] implementation which holds it in a static context,
* so that the same cache can be reused through the app processes life.
*/
internal object RoadShieldContentManagerContainer : RoadShieldContentManager {
private const val SPRITES_CACHE_SIZE = 8 // entries
private const val IMAGES_CACHE_SIZE = 40 // entries

private val contentManager: RoadShieldContentManager by lazy {
RoadShieldContentManagerImpl()
RoadShieldContentManagerImpl(
shieldLoader = CachedResourceLoader(
IMAGES_CACHE_SIZE,
RoadShieldLoader(
spritesLoader = CachedResourceLoader(
SPRITES_CACHE_SIZE,
ShieldSpritesDownloader()
),
imageLoader = { url ->
RoadShieldDownloader.download(url)
}
)
)
)
}

override suspend fun getShields(shieldsToDownload: List<RouteShieldToDownload>) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package com.mapbox.navigation.ui.shield
import com.mapbox.api.directions.v5.models.BannerComponents
import com.mapbox.bindgen.Expected
import com.mapbox.bindgen.ExpectedFactory
import com.mapbox.navigation.ui.shield.internal.loader.ResourceLoader
import com.mapbox.navigation.ui.shield.internal.model.RouteShieldToDownload
import com.mapbox.navigation.ui.shield.model.RouteShield
import com.mapbox.navigation.ui.shield.model.RouteShieldError
import com.mapbox.navigation.ui.shield.model.RouteShieldOrigin
import com.mapbox.navigation.ui.shield.model.RouteShieldResult
Expand Down Expand Up @@ -67,7 +69,7 @@ import kotlin.coroutines.resume
* - If request fails: repeat step 1.
*/
internal class RoadShieldContentManagerImpl(
private val shieldResultCache: ShieldResultCache = ShieldResultCache()
private val shieldLoader: ResourceLoader<RouteShieldToDownload, RouteShield>
) : RoadShieldContentManager {
internal companion object {
internal const val CANCELED_MESSAGE = "canceled"
Expand Down Expand Up @@ -116,11 +118,11 @@ internal class RoadShieldContentManagerImpl(
mainJob.scope.launch {
when (toDownload) {
is RouteShieldToDownload.MapboxDesign -> {
val mapboxDesignShieldResult = shieldResultCache.getOrRequest(toDownload)
val mapboxDesignShieldResult = shieldLoader.load(toDownload)
resultMap[request] = if (mapboxDesignShieldResult.isError) {
val legacyFallback = toDownload.legacyFallback
if (legacyFallback != null) {
shieldResultCache.getOrRequest(legacyFallback).fold(
shieldLoader.load(legacyFallback).fold(
{ error ->
ExpectedFactory.createError(
RouteShieldError(
Expand Down Expand Up @@ -172,7 +174,7 @@ internal class RoadShieldContentManagerImpl(
}
}
is RouteShieldToDownload.MapboxLegacy -> {
resultMap[request] = shieldResultCache.getOrRequest(toDownload).fold(
resultMap[request] = shieldLoader.load(toDownload).fold(
{ error ->
ExpectedFactory.createError(
RouteShieldError(
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
package com.mapbox.navigation.ui.shield
package com.mapbox.navigation.ui.shield.internal

import com.mapbox.bindgen.Expected
import com.mapbox.bindgen.ExpectedFactory.createError
import com.mapbox.bindgen.ExpectedFactory.createValue
import com.mapbox.bindgen.ExpectedFactory
import com.mapbox.common.ResourceLoadStatus
import com.mapbox.navigation.ui.utils.internal.resource.ResourceLoadRequest
import com.mapbox.navigation.ui.utils.internal.resource.ResourceLoader
Expand All @@ -21,19 +20,19 @@ internal object RoadShieldDownloader {
ResourceLoadStatus.AVAILABLE -> {
val blob: ByteArray = responseData.data?.data ?: byteArrayOf()
if (blob.isNotEmpty()) {
createValue(blob)
ExpectedFactory.createValue(blob)
} else {
createError("No data available.")
ExpectedFactory.createError("No data available.")
}
}
ResourceLoadStatus.UNAUTHORIZED ->
createError("Your token cannot access this resource.")
ExpectedFactory.createError("Your token cannot access this resource.")
ResourceLoadStatus.NOT_FOUND ->
createError("Resource is missing.")
ExpectedFactory.createError("Resource is missing.")
else ->
createError("Unknown error (status: ${responseData.status}).")
ExpectedFactory.createError("Unknown error (status: ${responseData.status}).")
}
} ?: createError(response.error?.message ?: "No data available.")
} ?: ExpectedFactory.createError(response.error?.message ?: "No data available.")
}

private suspend fun ResourceLoader.load(url: String) = load(ResourceLoadRequest(url))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.mapbox.navigation.ui.shield.internal.loader

import android.util.LruCache
import com.mapbox.bindgen.Expected

/**
* Resource Loader backed by LruCache
*/
internal class CachedResourceLoader<Argument, Resource>(
cacheSize: Int,
private val loader: ResourceLoader<Argument, Resource>
) : ResourceLoader<Argument, Resource> {

private val cache = LruCache<Argument, Expected<String, Resource>>(cacheSize)

override suspend fun load(argument: Argument): Expected<String, Resource> {
var value = cache.get(argument)
if (value != null) {
return value
}

value = loader.load(argument)
cache.put(argument, value)
return value
}
}
Loading