From 3519c7f69987f335a1745e06c2d473cb11b3106d Mon Sep 17 00:00:00 2001 From: Johan von Forstner Date: Wed, 30 Dec 2020 20:01:47 +0100 Subject: [PATCH] decrease memory usage of charger icons by allowing "fault" and "highlight" only with scale == 1f refs #59 --- .../vonforst/evmap/fragment/MapFragment.kt | 10 +++- .../net/vonforst/evmap/ui/IconGenerators.kt | 50 +++++++++++-------- .../java/net/vonforst/evmap/ui/MarkerUtils.kt | 8 +-- 3 files changed, 43 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/net/vonforst/evmap/fragment/MapFragment.kt b/app/src/main/java/net/vonforst/evmap/fragment/MapFragment.kt index 47308917..75d5f675 100644 --- a/app/src/main/java/net/vonforst/evmap/fragment/MapFragment.kt +++ b/app/src/main/java/net/vonforst/evmap/fragment/MapFragment.kt @@ -54,7 +54,9 @@ import com.mapzen.android.lost.api.LocationServices import com.mapzen.android.lost.api.LostApiClient import io.michaelrocks.bimap.HashBiMap import io.michaelrocks.bimap.MutableBiMap +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import net.vonforst.evmap.* import net.vonforst.evmap.adapter.ConnectorAdapter import net.vonforst.evmap.adapter.DetailsAdapter @@ -639,6 +641,12 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac override fun onMapReady(map: AnyMap) { this.map = map chargerIconGenerator = ChargerIconGenerator(requireContext(), map.bitmapDescriptorFactory) + lifecycleScope.launch { + withContext(Dispatchers.IO) { + chargerIconGenerator.preloadCache() + } + } + animator = MarkerAnimator(chargerIconGenerator) map.uiSettings.setTiltGesturesEnabled(false) map.setIndoorEnabled(false) @@ -822,7 +830,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac .icon( chargerIconGenerator.getBitmapDescriptor( tint, - 0, + 0f, 255, highlight, fault, diff --git a/app/src/main/java/net/vonforst/evmap/ui/IconGenerators.kt b/app/src/main/java/net/vonforst/evmap/ui/IconGenerators.kt index a5cf89c7..4a4cb597 100644 --- a/app/src/main/java/net/vonforst/evmap/ui/IconGenerators.kt +++ b/app/src/main/java/net/vonforst/evmap/ui/IconGenerators.kt @@ -16,6 +16,7 @@ import com.car2go.maps.model.BitmapDescriptor import com.google.maps.android.ui.IconGenerator import com.google.maps.android.ui.SquareTextView import net.vonforst.evmap.R +import kotlin.math.roundToInt class ClusterIconGenerator(context: Context) : IconGenerator(context) { init { @@ -41,8 +42,11 @@ class ClusterIconGenerator(context: Context) : IconGenerator(context) { } -class ChargerIconGenerator(val context: Context, val factory: BitmapDescriptorFactory) { - data class BitmapData( +class ChargerIconGenerator( + val context: Context, val factory: BitmapDescriptorFactory, + val scaleResolution: Int = 20 +) { + private data class BitmapData( val tint: Int, val scale: Int, val alpha: Int, @@ -51,20 +55,17 @@ class ChargerIconGenerator(val context: Context, val factory: BitmapDescriptorFa val multi: Boolean ) - val cacheSize = 840; // 840 items: 21 sizes, 5 colors, highlight, fault, multi on/off - val cache = LruCache(cacheSize) - val oversize = 1.4f // increase to add padding for fault icon or scale > 1 - val icon = R.drawable.ic_map_marker_charging - val multiIcon = R.drawable.ic_map_marker_charging_multiple - val highlightIcon = R.drawable.ic_map_marker_highlight - val highlightIconMulti = R.drawable.ic_map_marker_charging_highlight_multiple - val faultIcon = R.drawable.ic_map_marker_fault + // 230 items: (21 sizes, 5 colors, multi on/off) + highlight + fault (only with scale = 1) + private val cacheSize = (scaleResolution + 3) * 5 * 2; + private val cache = LruCache(cacheSize) + private val oversize = 1.4f // increase to add padding for fault icon or scale > 1 + private val icon = R.drawable.ic_map_marker_charging + private val multiIcon = R.drawable.ic_map_marker_charging_multiple + private val highlightIcon = R.drawable.ic_map_marker_highlight + private val highlightIconMulti = R.drawable.ic_map_marker_charging_highlight_multiple + private val faultIcon = R.drawable.ic_map_marker_fault - init { - preloadCache() - } - - private fun preloadCache() { + fun preloadCache() { // pre-generates images for scale from 0 to 255 for all possible tint colors val tints = listOf( R.color.charger_100kw, @@ -77,8 +78,11 @@ class ChargerIconGenerator(val context: Context, val factory: BitmapDescriptorFa for (highlight in listOf(false, true)) { for (multi in listOf(false, true)) { for (tint in tints) { - for (scale in 0..20) { - getBitmapDescriptor(tint, scale, 255, highlight, fault, multi) + for (scale in 0..scaleResolution) { + getBitmapDescriptor( + tint, scale.toFloat() / scaleResolution, + 255, highlight, fault, multi + ) } } } @@ -88,13 +92,19 @@ class ChargerIconGenerator(val context: Context, val factory: BitmapDescriptorFa fun getBitmapDescriptor( @ColorRes tint: Int, - scale: Int = 20, + scale: Float = 1f, alpha: Int = 255, highlight: Boolean = false, fault: Boolean = false, multi: Boolean = false ): BitmapDescriptor? { - val data = BitmapData(tint, scale, alpha, highlight, fault, multi) + val data = BitmapData( + tint, (scale * scaleResolution).roundToInt(), + alpha, + if (scale == 1f) highlight else false, + if (scale == 1f) fault else false, + multi + ) val cachedImg = cache[data] return if (cachedImg != null) { cachedImg @@ -128,7 +138,7 @@ class ChargerIconGenerator(val context: Context, val factory: BitmapDescriptorFa ) val canvas = Canvas(bm) - val scale = data.scale / 20f + val scale = data.scale.toFloat() / scaleResolution canvas.scale( scale, scale, diff --git a/app/src/main/java/net/vonforst/evmap/ui/MarkerUtils.kt b/app/src/main/java/net/vonforst/evmap/ui/MarkerUtils.kt index 302f76a4..04c62750 100644 --- a/app/src/main/java/net/vonforst/evmap/ui/MarkerUtils.kt +++ b/app/src/main/java/net/vonforst/evmap/ui/MarkerUtils.kt @@ -36,11 +36,11 @@ class MarkerAnimator(val gen: ChargerIconGenerator) { animatingMarkers.remove(marker) } - val anim = ValueAnimator.ofInt(0, 20).apply { + val anim = ValueAnimator.ofFloat(0f, 1f).apply { duration = 250 interpolator = LinearOutSlowInInterpolator() addUpdateListener { animationState -> - val scale = animationState.animatedValue as Int + val scale = animationState.animatedValue as Float marker.setIcon( gen.getBitmapDescriptor( tint, @@ -73,11 +73,11 @@ class MarkerAnimator(val gen: ChargerIconGenerator) { animatingMarkers.remove(marker) } - val anim = ValueAnimator.ofInt(20, 0).apply { + val anim = ValueAnimator.ofFloat(1f, 0f).apply { duration = 200 interpolator = FastOutLinearInInterpolator() addUpdateListener { animationState -> - val scale = animationState.animatedValue as Int + val scale = animationState.animatedValue as Float marker.setIcon( gen.getBitmapDescriptor( tint,