Fresco Image Management for Android

repository·main·Indexed 12 days ago

https://github.com/facebook/fresco

A powerful image management system for Android applications that handles loading, caching, and displaying images from network, local, or resource sources. Key features include two-level caching, memory management to reduce OutOfMemoryError on Android 4.x, and support for progressive JPEGs, animated GIFs, and WebPs. Provides extensibility through custom ImageDecoder and DrawableFactory implementations.

Tokens
36.5K
Snippets
93
Records
157
Agent score
96%

What's inside Fresco

  1. Overview of Fresco capabilities

    main

    Fresco is an image management system for Android that handles loading and displaying images from various sources including the network, local storage, or local resources.

    Key features include:

    • Automatic Loading & Placeholders: Manages the lifecycle of image loading and displays placeholders until the image is ready.
    • Two-Level Caching: Utilizes both an in-memory cache and an internal storage cache.
    • Memory Management: On Android 4.x and lower, Fresco uses a special region of Android memory to reduce OutOfMemoryError occurrences.
    • Advanced Formats: Supports streaming progressive JPEGs and displaying animated GIFs and WebPs.
    • Customization: Provides extensive options for customizing how images are loaded and displayed.
  2. Understand the Fresco Image Pipeline

    main

    Fresco's image pipeline manages the loading of images from various sources, including the network, local storage, or local resources. To optimize performance and reduce CPU usage, the pipeline utilizes a three-level caching system:

    1. Two levels of in-memory cache
    2. One level of internal storage cache
  3. Define a custom progress bar

    main

    To create a custom progress indicator, extend the Drawable class. To ensure the progress bar accurately reflects the loading state, you must override the onLevelChange(int level) method.

    Note that the level parameter is provided on a scale of 0 to 10,000, where 10,000 represents a fully downloaded image. Use this value within your implementation to update the drawable's appearance.

    class CustomProgressBar extends Drawable {
       @Override
       protected boolean onLevelChange(int level) {
         // level is on a scale of 0-10,000
         // where 10,000 means fully downloaded
    
         // your app's logic to change the drawable's
         // appearance here based on progress
       }
    }
  4. How to round image corners and create circles

    main

    Fresco (via Drawee) supports two primary shapes for images: circles and rounded rectangles. This is achieved without the memory overhead of copying bitmaps.

    Supported Shapes

    1. Circle: Set roundAsCircle to true.
    2. Rounded Rectangle: Set roundedCornerRadius to a specific value. You can specify different radii for each of the four corners via Java code.

    Rounding Methods

    There are two ways to implement rounding, each with different trade-offs:

    1. BITMAP_ONLY (Default): Uses a bitmap shader.

      • Pros: Most common method.
      • Cons: Does not support animations. Only supports centerCrop, focusCrop, and fit_xy scale types. If using other scale types (like center), you may see repeated edges if the image is smaller than the view.
      • Limitations: Only works with BitmapDrawable or ColorDrawable. Does not work with NinePatchDrawable or ShapeDrawable.
    2. OVERLAY_COLOR: Draws rounded corners by overlaying a solid color over the image.

      • Pros: Avoids BITMAP_ONLY limitations (supports animations and more scale types).
      • Cons: Requires the Drawee's background to be a static color that matches the overlay color to look seamless.
  5. Set the Actual image

    main

    The actual image is the primary target image. Unlike other branches, it is managed by the controller rather than the hierarchy.

    To set the actual image, use:

    • setImageURI(uri)
    • Or build a custom controller using setController.

    Specific properties available only for the actual image include:

    • Scale Type: Defaults to centerCrop.
    • Focus Point: Used specifically with the focusCrop scale type.
    • Color Filter.
  6. Handle Animated GIFs and WebPs

    main
    Fresco manages the complexities of animated GIFs and WebPs. It handles the loading and disposal of individual animation frames and manages the associated memory, which is critical since each frame is a large Bitmap.
  7. Trim caches for memory or disk pressure

    main

    Fresco's caches implement DiskTrimmable and MemoryTrimmable interfaces. This allows your application to trigger emergency evictions when the device is low on storage or memory.

    To implement this, you must configure the pipeline with objects implementing DiskTrimmableRegistry and MemoryTrimmableRegistry. These registries should maintain a list of trimmables and use your app-specific logic to decide when to notify them to perform a trim.

  8. Specify a custom DataSource Supplier

    main

    For advanced loading logic, you can provide a custom DataSource Supplier when building a DraweeController. This allows you to implement custom selection logic or compose existing suppliers.

    Reference implementations include:

    • FirstAvailableDataSourceSupplier
    • IncreasingQualityDataSourceSupplier

    See AbstractDraweeControllerBuilder for details on how to compose these suppliers.

  9. Use BitmapTransformation for in-place modifications

    main

    If you do not need to keep the original version of an image (e.g., for circular profile pictures), use a BitmapTransformation instead of a PostProcessor.

    Advantages:

    • Applied immediately after decoding.
    • The original image is not cached, saving memory.
    • No additional Bitmap allocation is required because it modifies the original directly.

    Implement the transform(Bitmap bitmap) method to perform the modification.

    public class CircularBitmapTransformation implements BitmapTransformation {
      @Override
      public void transform(Bitmap bitmap) {
        NativeRoundingFilter.toCircle(bitmap);
      }
    
      @Override
      public boolean modifiesTransparency() {
        return true; // Indicates the transformation uses transparent pixels
      }
    }
  10. Modify an image before displaying

    main
    The recommended way to apply transformations or modifications to an image before it is displayed is to implement a PostProcessor. This approach allows the image pipeline to perform the modification on a background thread and ensures efficient Bitmap allocation.
  11. Understand the Fresco Image Pipeline lifecycle

    main

    The Fresco image pipeline manages the end-to-end process of retrieving, decoding, and transforming an image for rendering on Android. When an image is requested, the pipeline follows a hierarchical lookup and caching strategy to minimize latency and resource usage:

    1. Bitmap Cache: The first check. If the decoded bitmap is present, it is returned immediately.
    2. Encoded Memory Cache: If not in the bitmap cache, the pipeline checks for the encoded image in memory. If found, it is decoded, transformed, and stored in the bitmap cache.
    3. Disk Cache: If not in memory, the pipeline checks the disk. If found, the image is decoded, transformed, and stored in both the encoded memory cache and the bitmap cache.
    4. Network/Original Source: If all caches miss, the image is fetched from the network or original source. Once retrieved, it is decoded, transformed, and stored in the disk cache, encoded memory cache, and bitmap cache.

    Supported formats include PNG, GIF, WebP, and JPEG. The pipeline supports loading from both local files and network URIs.