From 04fef1e5d2bbb4c29b26c67f67ad5229040b9857 Mon Sep 17 00:00:00 2001 From: Johan von Forstner Date: Sun, 12 Apr 2020 19:37:01 +0200 Subject: [PATCH] improve animation performance --- .../com/johan/evmap/fragment/MapFragment.kt | 5 +- .../java/com/johan/evmap/ui/IconGenerators.kt | 51 ++++++++++++++----- .../java/com/johan/evmap/ui/MarkerUtils.kt | 16 ++---- 3 files changed, 44 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/com/johan/evmap/fragment/MapFragment.kt b/app/src/main/java/com/johan/evmap/fragment/MapFragment.kt index c57a250f..1cc3b584 100644 --- a/app/src/main/java/com/johan/evmap/fragment/MapFragment.kt +++ b/app/src/main/java/com/johan/evmap/fragment/MapFragment.kt @@ -302,10 +302,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac MarkerOptions() .position(LatLng(charger.coordinates.lat, charger.coordinates.lng)) .icon( - chargerIconGenerator.getBitmapDescriptor( - R.drawable.ic_map_marker_charging, - tint - ) + chargerIconGenerator.getBitmapDescriptor(tint) ) ) animateMarkerAppear(marker, tint, chargerIconGenerator) diff --git a/app/src/main/java/com/johan/evmap/ui/IconGenerators.kt b/app/src/main/java/com/johan/evmap/ui/IconGenerators.kt index 8aa0c40b..e888bb4b 100644 --- a/app/src/main/java/com/johan/evmap/ui/IconGenerators.kt +++ b/app/src/main/java/com/johan/evmap/ui/IconGenerators.kt @@ -5,9 +5,9 @@ import android.graphics.Bitmap import android.graphics.Canvas import android.graphics.PorterDuff import android.graphics.drawable.Drawable +import android.util.LruCache import android.view.ViewGroup import androidx.annotation.ColorRes -import androidx.annotation.DrawableRes import androidx.core.content.ContextCompat import androidx.core.graphics.drawable.DrawableCompat import com.google.android.gms.maps.model.BitmapDescriptor @@ -40,29 +40,56 @@ class ClusterIconGenerator(context: Context) : IconGenerator(context) { class ChargerIconGenerator(val context: Context) { - data class BitmapData(val id: Int, val tint: Int, val scale: Int, val alpha: Int) + data class BitmapData(val tint: Int, val scale: Int, val alpha: Int) - val cache = hashMapOf() + val cacheSize = 4 * 1024 * 1024; // 4MiB + val cache = object : LruCache(cacheSize) { + override fun sizeOf(key: BitmapData, value: Bitmap): Int { + return value.byteCount + } + } val oversize = 1.5f + val icon = R.drawable.ic_map_marker_charging + + init { + preloadCache() + } + + fun preloadCache() { + // pre-generates images for scale from 0 to 255 for all possible tint colors + val tints = listOf( + R.color.charger_100kw, + R.color.charger_43kw, + R.color.charger_20kw, + R.color.charger_11kw, + R.color.charger_low + ) + for (tint in tints) { + for (scale in 0..20) { + val data = BitmapData(tint, scale, 255) + cache.put(data, generateBitmap(data)) + } + } + } fun getBitmapDescriptor( - @DrawableRes id: Int, @ColorRes tint: Int, - scale: Int = 255, + scale: Int = 20, alpha: Int = 255 ): BitmapDescriptor? { - val data = BitmapData(id, tint, scale, alpha) - if (cache.containsKey(data)) { - return BitmapDescriptorFactory.fromBitmap(cache[data]) + val data = BitmapData(tint, scale, alpha) + val cachedImg = cache[data] + return if (cachedImg != null) { + BitmapDescriptorFactory.fromBitmap(cachedImg) } else { val bitmap = generateBitmap(data) - cache[data] = bitmap - return BitmapDescriptorFactory.fromBitmap(bitmap) + cache.put(data, bitmap) + BitmapDescriptorFactory.fromBitmap(bitmap) } } private fun generateBitmap(data: BitmapData): Bitmap { - val vd: Drawable = context.getDrawable(data.id)!! + val vd: Drawable = context.getDrawable(icon)!! DrawableCompat.setTint(vd, ContextCompat.getColor(context, data.tint)); DrawableCompat.setTintMode(vd, PorterDuff.Mode.MULTIPLY); @@ -82,7 +109,7 @@ class ChargerIconGenerator(val context: Context) { ) val canvas = Canvas(bm) - val scale = data.scale / 255f + val scale = data.scale / 20f canvas.scale( scale, scale, diff --git a/app/src/main/java/com/johan/evmap/ui/MarkerUtils.kt b/app/src/main/java/com/johan/evmap/ui/MarkerUtils.kt index 23dfcbaf..b2a4e51c 100644 --- a/app/src/main/java/com/johan/evmap/ui/MarkerUtils.kt +++ b/app/src/main/java/com/johan/evmap/ui/MarkerUtils.kt @@ -21,7 +21,7 @@ fun animateMarkerAppear( tint: Int, gen: ChargerIconGenerator ) { - ValueAnimator.ofInt(0, 255).apply { + ValueAnimator.ofInt(0, 20).apply { duration = 250 interpolator = LinearOutSlowInInterpolator() addUpdateListener { animationState -> @@ -31,11 +31,7 @@ fun animateMarkerAppear( } val scale = animationState.animatedValue as Int marker.setIcon( - gen.getBitmapDescriptor( - R.drawable.ic_map_marker_charging, - tint, - scale = scale - ) + gen.getBitmapDescriptor(tint, scale = scale) ) } }.start() @@ -46,7 +42,7 @@ fun animateMarkerDisappear( tint: Int, gen: ChargerIconGenerator ) { - ValueAnimator.ofInt(255, 0).apply { + ValueAnimator.ofInt(20, 0).apply { duration = 200 interpolator = FastOutLinearInInterpolator() addUpdateListener { animationState -> @@ -56,11 +52,7 @@ fun animateMarkerDisappear( } val scale = animationState.animatedValue as Int marker.setIcon( - gen.getBitmapDescriptor( - R.drawable.ic_map_marker_charging, - tint, - scale = scale - ) + gen.getBitmapDescriptor(tint, scale = scale) ) } addListener(onEnd = {