androidengineers.Book a session

Battery & Network Optimization

Image Optimization (WebP/Vectors)

article20 minMedium

Images are the #1 cause of APK bloat and the #1 network payload for most apps. Choosing the right format and delivery strategy directly impacts download size, render time, and memory.

WebP: Replace PNG and JPEG

WebP provides better compression than both PNG and JPEG at the same visual quality:

FormatLosslessLossyTypical size vs PNG
PNGBaseline
JPEG~60% of PNG
WebP (lossless)~25% smaller than PNG
WebP (lossy)~30% smaller than JPEG

Android support:

  • WebP lossless/alpha: API 18+
  • WebP lossy: API 14+

Convert in Android Studio: Right-click any PNG/JPEG → Convert to WebP... → choose quality (80–90 is usually indistinguishable from original).

Convert via CLI:

# Install: brew install webp
cwebp -q 80 input.png -o output.webp

Vector Drawables: Scalable Icons

Use VectorDrawable for icons, illustrations, and any graphic that needs to render at multiple densities. One .xml file instead of 5 PNG densities (mdpi, hdpi, xhdpi, xxhdpi, xxxhdpi):

<!-- ic_arrow.xml — scales perfectly at any density -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24">
    <path
        android:fillColor="@color/on_surface"
        android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z" />
</vector>

Using in code:

imageView.setImageDrawable(
    AppCompatResources.getDrawable(context, R.drawable.ic_arrow)
)
// Or in XML:
// android:src="@drawable/ic_arrow"

Animated Vector Drawables

Replace GIFs with AnimatedVectorDrawable for small looping animations:

<!-- res/drawable/loading_animation.xml -->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/ic_loading">
    <target
        android:name="rotation_group"
        android:animation="@animator/rotate_360" />
</animated-vector>
val animatable = AnimatedVectorDrawableCompat.create(context, R.drawable.loading_animation)
imageView.setImageDrawable(animatable)
animatable?.start()

Dynamic Image Sizing via URL Parameters

When serving images from a CDN, request only the resolution you need:

fun ImageView.loadOptimized(imageUrl: String) {
    // Request image at 2× display size (for high-density screens)
    val widthPx = width.takeIf { it > 0 } ?: 400
    val heightPx = height.takeIf { it > 0 } ?: 300
    val density = resources.displayMetrics.density.toInt()

    val optimizedUrl = "$imageUrl?w=${widthPx * density}&h=${heightPx * density}&fmt=webp&q=80"

    load(optimizedUrl) {
        placeholder(R.drawable.placeholder)
        crossfade(true)
    }
}

APK Image Asset Checklist

RuleReasoning
Convert all PNGs/JPEGs ≥ 10 KB to WebP25–30% APK size reduction
Use vectors for icons < 200×200dpOne file vs 5 density buckets
Use 9-patch (.9.png) for scalable stretchable imagesAvoids large background bitmaps
Check with aapt dump badging for density coverageVerify all required densities are present
Profile with resconfigs to strip unused densitiesRemoves densities not in your supported set
// build.gradle.kts — strip unused languages and densities (reduces APK)
android {
    defaultConfig {
        resourceConfigurations += setOf("en", "xxhdpi", "xxxhdpi")
    }
}

Key Takeaways

  • WebP lossless saves ~25% vs PNG; lossy saves ~30% vs JPEG with comparable quality
  • VectorDrawable replaces 5 density PNG files with one XML — use for all icons and simple illustrations
  • Request CDN images at display size × density, in WebP format
  • AnimatedVectorDrawable is the GIF replacement for small looping animations

YOUR LEARNING JOURNEY

0 of 177 available lessons completed

Progress saved in this browser. No account needed.
Image Optimization (WebP/Vectors) | Android System Design | Android Engineers