CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-airbnb-android--lottie

Android library for rendering Adobe After Effects animations exported as JSON through Bodymovin with native performance and extensive customization options.

Pending
Overview
Eval results
Files

configuration-performance.mddocs/

Configuration and Performance

Global configuration, render mode settings, performance optimization options, and monitoring tools for Lottie Android applications.

Capabilities

Global Configuration

System for configuring global Lottie settings including network fetching, caching, and debugging options.

/**
 * Global configuration class
 */
public class Lottie {
    /**
     * Initialize Lottie with global configuration
     * @param config Configuration instance
     */
    public static void initialize(LottieConfig config);
}

/**
 * Configuration builder for global Lottie settings
 */
public class LottieConfig {
    // Internal configuration
    final LottieNetworkFetcher networkFetcher;
    final LottieNetworkCacheProvider cacheProvider;
    final boolean enableSystraceMarkers;
    
    // Private constructor - use Builder
    private LottieConfig(LottieNetworkFetcher networkFetcher, 
                        LottieNetworkCacheProvider cacheProvider,
                        boolean enableSystraceMarkers);
    
    /**
     * Builder for LottieConfig
     */
    public static final class Builder {
        // Network configuration
        public Builder setNetworkFetcher(LottieNetworkFetcher fetcher);
        public Builder setNetworkCacheDir(File file);
        public Builder setNetworkCacheProvider(LottieNetworkCacheProvider fileCacheProvider);
        
        // Performance configuration
        public Builder setEnableSystraceMarkers(boolean enable);
        
        // Build configuration
        public LottieConfig build();
    }
}

Usage Examples:

// Basic global configuration
LottieConfig config = new LottieConfig.Builder()
    .setNetworkCacheDir(new File(getCacheDir(), "lottie_animations"))
    .setEnableSystraceMarkers(BuildConfig.DEBUG)
    .build();

Lottie.initialize(config);

// Custom network fetcher configuration
LottieConfig config = new LottieConfig.Builder()
    .setNetworkFetcher(new CustomNetworkFetcher())
    .setNetworkCacheDir(new File(getExternalCacheDir(), "lottie_cache"))
    .build();

Lottie.initialize(config);

// Production configuration
LottieConfig prodConfig = new LottieConfig.Builder()
    .setNetworkCacheProvider(() -> new File(getCacheDir(), "lottie_network_cache"))
    .setEnableSystraceMarkers(false) // Disable in production
    .build();

Lottie.initialize(prodConfig);

// Development configuration with debugging
LottieConfig devConfig = new LottieConfig.Builder()
    .setNetworkFetcher(new LoggingNetworkFetcher())
    .setNetworkCacheDir(new File(getCacheDir(), "dev_lottie_cache"))
    .setEnableSystraceMarkers(true) // Enable for performance analysis
    .build();

Lottie.initialize(devConfig);

Render Mode Configuration

System for configuring rendering performance by choosing between hardware acceleration, software rendering, or automatic selection.

/**
 * Rendering mode configuration
 */
public enum RenderMode {
    AUTOMATIC, // Automatic selection based on animation characteristics
    HARDWARE,  // Force hardware acceleration
    SOFTWARE;  // Force software rendering
    
    /**
     * Determine if software rendering should be used
     * @param sdkInt Android SDK version
     * @param hasDashPattern Whether animation has dash patterns
     * @param numMasksAndMattes Number of masks and mattes
     * @return true if software rendering should be used
     */
    public boolean useSoftwareRendering(int sdkInt, boolean hasDashPattern, int numMasksAndMattes);
}

Usage Examples:

// Set render mode on view
animationView.setRenderMode(RenderMode.HARDWARE); // Force hardware acceleration
drawable.setRenderMode(RenderMode.SOFTWARE); // Force software rendering

// Automatic mode (default) - chooses based on animation characteristics
animationView.setRenderMode(RenderMode.AUTOMATIC);

// Check current render mode
RenderMode currentMode = animationView.getRenderMode();
Log.d("Lottie", "Current render mode: " + currentMode);

// Dynamic render mode selection based on device capabilities
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
    // Newer devices handle hardware acceleration better
    animationView.setRenderMode(RenderMode.HARDWARE);
} else {
    // Older devices may perform better with software rendering
    animationView.setRenderMode(RenderMode.SOFTWARE);
}

// Conditional render mode based on animation complexity
LottieCompositionFactory.fromAsset(context, "complex_animation.json")
    .addListener(composition -> {
        animationView.setComposition(composition);
        
        // Choose render mode based on complexity
        if (composition.getMaskAndMatteCount() > 5 || composition.hasDashPattern()) {
            animationView.setRenderMode(RenderMode.SOFTWARE);
        } else {
            animationView.setRenderMode(RenderMode.HARDWARE);
        }
        
        animationView.playAnimation();
    });

// Custom render mode logic
public class SmartRenderModeHelper {
    public static RenderMode selectOptimalRenderMode(LottieComposition composition) {
        int sdkInt = Build.VERSION.SDK_INT;
        boolean hasDashPattern = composition.hasDashPattern();
        int masksAndMattes = composition.getMaskAndMatteCount();
        
        // Use RenderMode's built-in logic
        if (RenderMode.AUTOMATIC.useSoftwareRendering(sdkInt, hasDashPattern, masksAndMattes)) {
            return RenderMode.SOFTWARE;
        } else {
            return RenderMode.HARDWARE;
        }
    }
}

Performance Monitoring

Tools for monitoring and analyzing animation performance, including render time tracking and performance metrics.

/**
 * Performance tracking utility
 */
public class PerformanceTracker {
    // Enable/disable tracking
    public void setEnabled(boolean enabled);
    public boolean isEnabled();
    
    // Record performance data
    public void recordRenderTime(String layerName, float renderTimeMs);
    
    // Retrieve performance data
    public Map<String, Float> getSortedRenderTimes();
    public void clearRenderTimes();
    
    // Listener for performance events
    public void addFrameListener(FrameListener frameListener);
    public void removeFrameListener(FrameListener frameListener);
    
    // Internal methods
    @RestrictTo(RestrictTo.Scope.LIBRARY)
    public void startTimer(String layerName);
    @RestrictTo(RestrictTo.Scope.LIBRARY)
    public float endTimer(String layerName);
}

/**
 * Frame performance listener
 */
public interface FrameListener {
    void onFrameRendered(float renderTimeMs);
}

Usage Examples:

// Enable performance tracking
PerformanceTracker tracker = animationView.getPerformanceTracker();
tracker.setEnabled(true);

// Add frame listener for real-time monitoring
tracker.addFrameListener(renderTimeMs -> {
    if (renderTimeMs > 16.67f) { // Slower than 60fps
        Log.w("Lottie", "Slow frame detected: " + renderTimeMs + "ms");
    }
});

// Analyze performance after animation
animationView.addAnimatorListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animator) {
        Map<String, Float> renderTimes = tracker.getSortedRenderTimes();
        
        float totalTime = 0f;
        for (Map.Entry<String, Float> entry : renderTimes.entrySet()) {
            String layerName = entry.getKey();
            Float renderTime = entry.getValue();
            totalTime += renderTime;
            
            Log.d("Lottie", "Layer '" + layerName + "': " + renderTime + "ms");
        }
        
        Log.d("Lottie", "Total render time: " + totalTime + "ms");
        
        // Clear for next analysis
        tracker.clearRenderTimes();
    }
});

// Performance monitoring helper
public class LottiePerformanceMonitor {
    private static final float TARGET_FRAME_TIME = 16.67f; // 60fps
    private final PerformanceTracker tracker;
    private final List<Float> frameTimes = new ArrayList<>();
    
    public LottiePerformanceMonitor(LottieAnimationView animationView) {
        this.tracker = animationView.getPerformanceTracker();
        this.tracker.setEnabled(true);
        
        this.tracker.addFrameListener(frameTime -> {
            frameTimes.add(frameTime);
            
            // Alert on consistently slow frames
            if (frameTimes.size() >= 10) {
                float averageTime = calculateAverage(frameTimes.subList(frameTimes.size() - 10, frameTimes.size()));
                if (averageTime > TARGET_FRAME_TIME * 1.5f) {
                    Log.w("Lottie", "Performance warning: Average frame time " + averageTime + "ms");
                }
            }
        });
    }
    
    public PerformanceReport generateReport() {
        if (frameTimes.isEmpty()) {
            return new PerformanceReport();
        }
        
        float minTime = Collections.min(frameTimes);
        float maxTime = Collections.max(frameTimes);
        float avgTime = calculateAverage(frameTimes);
        int droppedFrames = (int) frameTimes.stream()
            .mapToDouble(Float::doubleValue)
            .filter(time -> time > TARGET_FRAME_TIME)
            .count();
        
        return new PerformanceReport(minTime, maxTime, avgTime, droppedFrames, frameTimes.size());
    }
    
    private float calculateAverage(List<Float> times) {
        return (float) times.stream().mapToDouble(Float::doubleValue).average().orElse(0.0);
    }
    
    public static class PerformanceReport {
        public final float minFrameTime;
        public final float maxFrameTime;
        public final float avgFrameTime;
        public final int droppedFrames;
        public final int totalFrames;
        
        public PerformanceReport() {
            this(0, 0, 0, 0, 0);
        }
        
        public PerformanceReport(float minFrameTime, float maxFrameTime, float avgFrameTime, 
                               int droppedFrames, int totalFrames) {
            this.minFrameTime = minFrameTime;
            this.maxFrameTime = maxFrameTime;
            this.avgFrameTime = avgFrameTime;
            this.droppedFrames = droppedFrames;
            this.totalFrames = totalFrames;
        }
        
        public float getFrameRate() {
            return avgFrameTime > 0 ? 1000f / avgFrameTime : 0f;
        }
        
        public float getDroppedFramePercentage() {
            return totalFrames > 0 ? (droppedFrames * 100f) / totalFrames : 0f;
        }
    }
}

Optimization Settings

Various settings for optimizing animation performance and behavior.

// Animation view optimization methods
public class LottieAnimationView extends AppCompatImageView {
    // Merge paths optimization (API 19+)
    public void enableMergePathsForKitKatAndAbove(boolean enable);
    
    // Opacity optimization
    public void setApplyingOpacityToLayersEnabled(boolean isApplyingOpacityToLayersEnabled);
    
    // Clipping optimization
    public void setClipToCompositionBounds(boolean clipToCompositionBounds);
    
    // System animation handling
    public void setIgnoreDisabledSystemAnimations(boolean ignore);
}

// Drawable optimization methods
public class LottieDrawable extends Drawable {
    // Merge paths optimization
    public void enableMergePathsForKitKatAndAbove(boolean enable);
    
    // Opacity optimization
    public void setApplyingOpacityToLayersEnabled(boolean isApplyingOpacityToLayersEnabled);
    
    // Clipping optimization
    public void setClipToCompositionBounds(boolean clipToCompositionBounds);
    
    // System animation handling
    public void setSystemAnimationsAreEnabled(boolean areSystemAnimationsEnabled);
    public void setIgnoreDisabledSystemAnimations(boolean ignore);
    
    // Safe mode for problematic animations
    public void setSafeMode(boolean safeMode);
    
    // Performance tracking
    public void setPerformanceTrackingEnabled(boolean enabled);
}

Usage Examples:

// Enable optimizations
animationView.enableMergePathsForKitKatAndAbove(true);
animationView.setApplyingOpacityToLayersEnabled(true);
animationView.setClipToCompositionBounds(true);

// Optimize for older devices
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
    animationView.setRenderMode(RenderMode.SOFTWARE);
    animationView.enableMergePathsForKitKatAndAbove(false);
}

// Handle system animation settings
animationView.setIgnoreDisabledSystemAnimations(false); // Respect user's animation settings

// Safe mode for problematic animations
drawable.setSafeMode(true); // Disable some optimizations for stability

// Performance-optimized setup
public void setupOptimizedLottieView(LottieAnimationView animationView, boolean isLowEndDevice) {
    if (isLowEndDevice) {
        // Conservative settings for low-end devices
        animationView.setRenderMode(RenderMode.SOFTWARE);
        animationView.enableMergePathsForKitKatAndAbove(false);
        animationView.setApplyingOpacityToLayersEnabled(false);
    } else {
        // Aggressive optimizations for high-end devices
        animationView.setRenderMode(RenderMode.HARDWARE);
        animationView.enableMergePathsForKitKatAndAbove(true);
        animationView.setApplyingOpacityToLayersEnabled(true);
        animationView.setClipToCompositionBounds(true);
    }
    
    // Common optimizations
    animationView.setIgnoreDisabledSystemAnimations(false);
}

// Memory optimization helper
public class LottieMemoryManager {
    private static final int MAX_CACHE_SIZE = 20;
    
    public static void optimizeForMemory() {
        // Limit composition cache size
        LottieCompositionFactory.setMaxCacheSize(MAX_CACHE_SIZE);
    }
    
    public static void clearAllCaches(Context context) {
        // Clear composition cache
        LottieCompositionFactory.clearCache(context);
        
        // Clear network cache
        File cacheDir = new File(context.getCacheDir(), "lottie_network_cache");
        if (cacheDir.exists()) {
            deleteRecursively(cacheDir);
        }
    }
    
    private static void deleteRecursively(File file) {
        if (file.isDirectory()) {
            File[] children = file.listFiles();
            if (children != null) {
                for (File child : children) {
                    deleteRecursively(child);
                }
            }
        }
        file.delete();
    }
}

Network Configuration

Configuration for network-based animation loading with custom fetchers and cache providers.

/**
 * Interface for custom network fetching
 */
public interface LottieNetworkFetcher {
    LottieResult<LottieComposition> fetchSync(String url, String cacheKey);
}

/**
 * Interface for custom cache providers
 */
public interface LottieNetworkCacheProvider {
    File getCacheDir();
}

/**
 * Network fetch result interface
 */
public interface LottieFetchResult {
    boolean isSuccessful();
    InputStream bodyByteStream();
    String contentType();
}

/**
 * Default network fetcher implementation
 */
public class DefaultLottieNetworkFetcher implements LottieNetworkFetcher {
    public DefaultLottieNetworkFetcher();
    public LottieResult<LottieComposition> fetchSync(String url, String cacheKey);
}

/**
 * Default fetch result implementation
 */
public class DefaultLottieFetchResult implements LottieFetchResult {
    public DefaultLottieFetchResult(HttpURLConnection connection);
    public boolean isSuccessful();
    public InputStream bodyByteStream();
    public String contentType();
}

Usage Examples:

// Custom network fetcher with authentication
public class AuthenticatedNetworkFetcher implements LottieNetworkFetcher {
    private final String authToken;
    
    public AuthenticatedNetworkFetcher(String authToken) {
        this.authToken = authToken;
    }
    
    @Override
    public LottieResult<LottieComposition> fetchSync(String url, String cacheKey) {
        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
            connection.setRequestProperty("Authorization", "Bearer " + authToken);
            connection.setRequestMethod("GET");
            connection.connect();
            
            DefaultLottieFetchResult fetchResult = new DefaultLottieFetchResult(connection);
            if (fetchResult.isSuccessful()) {
                InputStream inputStream = fetchResult.bodyByteStream();
                return LottieCompositionFactory.fromJsonInputStreamSync(inputStream, cacheKey);
            } else {
                return new LottieResult<>(new IOException("HTTP " + connection.getResponseCode()));
            }
        } catch (IOException e) {
            return new LottieResult<>(e);
        }
    }
}

// Custom cache provider
public class CustomCacheProvider implements LottieNetworkCacheProvider {
    private final File customCacheDir;
    
    public CustomCacheProvider(Context context) {
        this.customCacheDir = new File(context.getExternalCacheDir(), "custom_lottie_cache");
        if (!customCacheDir.exists()) {
            customCacheDir.mkdirs();
        }
    }
    
    @Override
    public File getCacheDir() {
        return customCacheDir;
    }
}

// Configure custom network handling
LottieConfig config = new LottieConfig.Builder()
    .setNetworkFetcher(new AuthenticatedNetworkFetcher(userToken))
    .setNetworkCacheProvider(new CustomCacheProvider(context))
    .build();

Lottie.initialize(config);

Logging and Debugging

public interface LottieLogger {
    void debug(String message);
    void debug(String message, Throwable exception);
    void warning(String message);
    void warning(String message, Throwable exception);
    void error(String message, Throwable exception);
}

public class LogcatLogger implements LottieLogger {
    public static final LogcatLogger INSTANCE = new LogcatLogger();
    
    @Override
    public void debug(String message);
    @Override
    public void debug(String message, Throwable exception);
    @Override
    public void warning(String message);
    @Override
    public void warning(String message, Throwable exception);
    @Override
    public void error(String message, Throwable exception);
}

Install with Tessl CLI

npx tessl i tessl/maven-com-airbnb-android--lottie

docs

asset-management.md

composition-loading.md

configuration-performance.md

dynamic-properties.md

index.md

view-components.md

tile.json