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

composition-loading.mddocs/

Composition Loading

Factory methods and async operations for loading Lottie animations from various sources including assets, raw resources, URLs, and streams. All loading operations return LottieTask instances for async handling with built-in caching support.

Capabilities

LottieCompositionFactory

Factory class providing static methods for loading animations from different sources. All methods return LottieTask<LottieComposition> for async handling.

/**
 * Factory for creating LottieComposition instances from various sources
 */
public class LottieCompositionFactory {
    // Asset loading
    public static LottieTask<LottieComposition> fromAsset(Context context, String fileName);
    public static LottieTask<LottieComposition> fromAsset(Context context, String fileName, String cacheKey);
    
    // Raw resource loading
    public static LottieTask<LottieComposition> fromRawRes(Context context, @RawRes int rawRes);
    public static LottieTask<LottieComposition> fromRawRes(Context context, @RawRes int rawRes, String cacheKey);
    
    // URL loading with caching
    public static LottieTask<LottieComposition> fromUrl(Context context, String url);
    public static LottieTask<LottieComposition> fromUrl(Context context, String url, String cacheKey);
    
    // JSON string loading
    public static LottieTask<LottieComposition> fromJsonString(String json, String cacheKey);
    public static LottieTask<LottieComposition> fromJsonInputStream(InputStream stream, String cacheKey);
    public static LottieTask<LottieComposition> fromJsonReader(JsonReader reader, String cacheKey);
    public static LottieTask<LottieComposition> fromJson(JSONObject json, String cacheKey);
    
    // ZIP file loading (for animations with images)
    public static LottieTask<LottieComposition> fromZipStream(ZipInputStream inputStream, String cacheKey);
    public static LottieTask<LottieComposition> fromZipStreamSync(ZipInputStream inputStream, String cacheKey);
    
    // Synchronous loading methods (use with caution on main thread)
    public static LottieResult<LottieComposition> fromAssetSync(Context context, String fileName);
    public static LottieResult<LottieComposition> fromAssetSync(Context context, String fileName, String cacheKey);
    public static LottieResult<LottieComposition> fromRawResSync(Context context, @RawRes int rawRes);
    public static LottieResult<LottieComposition> fromRawResSync(Context context, @RawRes int rawRes, String cacheKey);
    public static LottieResult<LottieComposition> fromUrlSync(Context context, String url);
    public static LottieResult<LottieComposition> fromUrlSync(Context context, String url, String cacheKey);
    public static LottieResult<LottieComposition> fromJsonStringSync(String json, String cacheKey);
    public static LottieResult<LottieComposition> fromJsonInputStreamSync(InputStream stream, String cacheKey);
    public static LottieResult<LottieComposition> fromJsonSync(JSONObject json, String cacheKey);
    public static LottieResult<LottieComposition> fromJsonReaderSync(JsonReader reader, String cacheKey);
    
    // Cache management
    public static void setMaxCacheSize(int size);
    public static void clearCache(Context context);
}

Usage Examples:

// Load from assets
LottieCompositionFactory.fromAsset(context, "animation.json")
    .addListener(composition -> {
        animationView.setComposition(composition);
        animationView.playAnimation();
    })
    .addFailureListener(throwable -> {
        Log.e("Lottie", "Failed to load animation", throwable);
    });

// Load from raw resources
LottieCompositionFactory.fromRawRes(context, R.raw.loading_animation)
    .addListener(animationView::setComposition);

// Load from URL with custom cache key
LottieCompositionFactory.fromUrl(context, "https://example.com/animation.json", "custom_key")
    .addListener(composition -> {
        drawable.setComposition(composition);
        drawable.playAnimation();
    });

// Load from JSON string
String animationJson = "{ ... }"; // Lottie JSON
LottieCompositionFactory.fromJsonString(animationJson, "inline_animation")
    .addListener(composition -> {
        // Use composition
    });

// Load from input stream
try (InputStream stream = new FileInputStream(animationFile)) {
    LottieCompositionFactory.fromJsonInputStream(stream, "file_animation")
        .addListener(composition -> {
            // Use composition
        });
}

// Load ZIP file (with images)
try (ZipInputStream zipStream = new ZipInputStream(new FileInputStream(zipFile))) {
    LottieCompositionFactory.fromZipStream(zipStream, "zip_animation")
        .addListener(composition -> {
            // Use composition
        });
}

// Synchronous loading (background thread only)
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(() -> {
    LottieResult<LottieComposition> result = 
        LottieCompositionFactory.fromAssetSync(context, "animation.json");
    
    if (result.getValue() != null) {
        // Success - switch to main thread to use composition
        Handler mainHandler = new Handler(Looper.getMainLooper());
        mainHandler.post(() -> {
            animationView.setComposition(result.getValue());
        });
    } else {
        Log.e("Lottie", "Failed to load", result.getException());
    }
});

// Cache management
LottieCompositionFactory.setMaxCacheSize(50); // Increase cache size
LottieCompositionFactory.clearCache(context); // Clear all cached animations

LottieComposition

Immutable composition model representing a parsed After Effects animation. Contains all animation data including layers, assets, timing information, and metadata.

/**
 * Immutable composition model representing parsed After Effects animation
 */
public class LottieComposition {
    // Bounds and dimensions
    public Rect getBounds();
    
    // Timing information
    public float getDuration(); // Duration in milliseconds
    public float getDurationAsSeconds(); // Duration in seconds
    public float getStartFrame();
    public float getEndFrame();
    public float getFrameRate();
    public float getDurationFrames(); // Duration in frames
    
    // Animation structure
    public List<Layer> getLayers();
    public LongSparseArray<Layer> getLayerMap();
    public Map<String, List<Layer>> getPrecomps();
    
    // Assets
    public Map<String, LottieImageAsset> getImages();
    public boolean hasImages();
    public Map<String, Font> getFonts();
    public SparseArrayCompat<FontCharacter> getCharacters();
    
    // Markers
    public List<Marker> getMarkers();
    public Marker getMarker(String markerName);
    
    // Performance characteristics
    public boolean hasDashPattern();
    public int getMaskAndMatteCount();
    
    // Debugging and analysis
    public Set<String> getWarnings();
    public PerformanceTracker getPerformanceTracker();
    
    // Internal methods (library use)
    @RestrictTo(RestrictTo.Scope.LIBRARY)
    public void addWarning(String warning);
    @RestrictTo(RestrictTo.Scope.LIBRARY)
    public void setHasDashPattern(boolean hasDashPattern);
    @RestrictTo(RestrictTo.Scope.LIBRARY)
    public void incrementMatteOrMaskCount(int amount);
}

Usage Examples:

// Analyze composition
LottieCompositionFactory.fromAsset(context, "complex_animation.json")
    .addListener(composition -> {
        Log.d("Lottie", "Duration: " + composition.getDurationAsSeconds() + "s");
        Log.d("Lottie", "Frame rate: " + composition.getFrameRate() + " fps");
        Log.d("Lottie", "Has images: " + composition.hasImages());
        Log.d("Lottie", "Mask/matte count: " + composition.getMaskAndMatteCount());
        
        // Check for markers
        List<Marker> markers = composition.getMarkers();
        for (Marker marker : markers) {
            Log.d("Lottie", "Marker: " + marker.getName() + 
                " at frame " + marker.getStartFrame());
        }
        
        // Check warnings
        Set<String> warnings = composition.getWarnings();
        if (!warnings.isEmpty()) {
            Log.w("Lottie", "Animation warnings: " + warnings);
        }
    });

// Use composition bounds for layout
composition.getBounds(); // Returns Rect with animation bounds
int width = composition.getBounds().width();
int height = composition.getBounds().height();

// Performance analysis
PerformanceTracker tracker = composition.getPerformanceTracker();
tracker.setEnabled(true);
// ... after animation plays
Map<String, Float> renderTimes = tracker.getSortedRenderTimes();

LottieTask

Async task wrapper for handling loading operations with success and failure callbacks. Provides chainable API for handling results.

/**
 * Async task helper for loading operations
 */
public class LottieTask<T> {
    // Result listeners
    public LottieTask<T> addListener(LottieListener<T> listener);
    public LottieTask<T> removeListener(LottieListener<T> listener);
    public LottieTask<T> addFailureListener(LottieListener<Throwable> listener);
    public LottieTask<T> removeFailureListener(LottieListener<Throwable> listener);
    
    // Static executor configuration
    public static Executor EXECUTOR; // Default: cached thread pool
}

Usage Examples:

// Chaining listeners
LottieCompositionFactory.fromAsset(context, "animation.json")
    .addListener(composition -> {
        // Success callback
        animationView.setComposition(composition);
        animationView.playAnimation();
    })
    .addFailureListener(throwable -> {
        // Error callback
        Log.e("Lottie", "Failed to load animation", throwable);
        showErrorState();
    })
    .addListener(composition -> {
        // Additional success callback
        enableAnimationControls();
    });

// Remove listeners
LottieListener<LottieComposition> listener = composition -> { /* ... */ };
LottieTask<LottieComposition> task = LottieCompositionFactory.fromAsset(context, "animation.json");
task.addListener(listener);
// Later...
task.removeListener(listener);

// Custom executor
LottieTask.EXECUTOR = Executors.newFixedThreadPool(2);

LottieResult

Result wrapper containing either a success value or an exception. Used by synchronous loading methods.

/**
 * Result wrapper for sync operations
 */
public class LottieResult<V> {
    public LottieResult(V value);
    public LottieResult(Throwable exception);
    
    public V getValue();
    public Throwable getException();
    
    @Override
    public boolean equals(Object o);
    @Override
    public int hashCode();
}

Usage Examples:

// Check result
LottieResult<LottieComposition> result = 
    LottieCompositionFactory.fromAssetSync(context, "animation.json");

if (result.getValue() != null) {
    LottieComposition composition = result.getValue();
    // Use composition
} else if (result.getException() != null) {
    Throwable error = result.getException();
    Log.e("Lottie", "Load failed", error);
}

Network Loading Configuration

public interface LottieNetworkFetcher {
    LottieResult<LottieComposition> fetchSync(String url, String cacheKey);
}

public interface LottieNetworkCacheProvider {
    File getCacheDir();
}

public interface LottieFetchResult {
    boolean isSuccessful();
    InputStream bodyByteStream();
    String contentType();
}

public class DefaultLottieNetworkFetcher implements LottieNetworkFetcher {
    public DefaultLottieNetworkFetcher();
    public LottieResult<LottieComposition> fetchSync(String url, String cacheKey);
}

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