You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Fresco加载本地图片内存占用过高问题排查求助

Troubleshooting Higher Memory Usage with Fresco for Local Image Display

Hey there! It makes total sense you're confused—using Fresco just to display local images shouldn't bloat your memory more than your old setup. Let's break down why this might be happening and fix it step by step.

Why Fresco's Using More Memory Out of the Box

Fresco's default initialization (Fresco.initialize(context)) sets up a memory cache tuned for full-featured use (including network downloads, large image sets, etc.). Even if you're not using the network part, the default cache size and overhead from unused features can add up. Plus, looking at your code, there are a few inefficiencies contributing to the problem.

Fixes to Reduce Memory Usage

1. Customize Fresco Initialization to Trim Unused Features & Shrink Cache

Since you only use Fresco for local files, you can disable network components and shrink the memory cache to match your actual needs. Here's how to set this up:

// In your Application class or initialization entry point
ImagePipelineConfig config = ImagePipelineConfig.newBuilder(context)
        // Disable network fetching entirely—we don't need it
        .setNetworkFetcher(new VoidNetworkFetcher())
        // Customize memory cache parameters to fit your app's constraints
        .setBitmapMemoryCacheParamsSupplier(new Supplier<MemoryCacheParams>() {
            @Override
            public MemoryCacheParams get() {
                // Adjust these values based on your app's memory limits
                final int maxCacheSize = (int) (Runtime.getRuntime().maxMemory() / 8); // 1/8 of total app memory
                final int maxCacheSizeOnLowMemory = (int) (Runtime.getRuntime().maxMemory() / 16); // Smaller for low-memory situations
                final int maxCacheEntries = 200; // Limit number of cached bitmaps
                return new MemoryCacheParams(
                        maxCacheSize,
                        maxCacheEntries,
                        maxCacheSizeOnLowMemory,
                        maxCacheEntries / 2,
                        Integer.MAX_VALUE
                );
            }
        })
        // Disable disk cache since we're loading local files directly
        .setMainDiskCacheConfig(DiskCacheConfig.newBuilder(context)
                .setEnabled(false)
                .build())
        .build();

Fresco.initialize(context, config);

2. Reuse GenericDraweeHierarchy Instead of Creating New Ones

In your current code, you build a new GenericDraweeHierarchy every time setImage runs. This creates unnecessary object overhead and increases garbage collection pressure. Instead, reuse hierarchies based on their configuration (rounded corners, fade duration):

// Cache hierarchies to avoid redundant creation
private static final HashMap<String, GenericDraweeHierarchy> HIERARCHY_CACHE = new HashMap<>();

private GenericDraweeHierarchy getOrCreateHierarchy(Context context, boolean fadeIn, boolean isRound) {
    // Create a unique key for this hierarchy's configuration
    String key = fadeIn + "_" + isRound;
    if (HIERARCHY_CACHE.containsKey(key)) {
        return HIERARCHY_CACHE.get(key);
    }

    GenericDraweeHierarchyBuilder builder = GenericDraweeHierarchyBuilder.newInstance(context.getResources());
    if (fadeIn) {
        builder.setFadeDuration(FADE_IN_TIME);
    }
    if (isRound) {
        builder.setRoundingParams(RoundingParams.asCircle());
    }
    GenericDraweeHierarchy hierarchy = builder.build();
    HIERARCHY_CACHE.put(key, hierarchy);
    return hierarchy;
}

// Updated setImage method using cached hierarchies
private void setImage(Context context, boolean isSvg, final SimpleDraweeView imageView, final String filePath, ImageData data) {
    GenericDraweeHierarchy hierarchy = getOrCreateHierarchy(context, data.isFadeInBitmap(), data.isRound());
    
    int width = imageView.getLayoutParams().width;
    int height = imageView.getLayoutParams().height;
    ImageRequestBuilder imageRequestBuilder = ImageRequestBuilder.newBuilderWithSource(UriUtil.getUriForFile(new File(filePath)));
    
    if (width > 0 && height > 0) {
        imageRequestBuilder.setResizeOptions(new ResizeOptions(width, height))
                // Enable downsampling to load a memory-efficient bitmap matching the ImageView size
                .setDownsampleEnabled(true);
    }
    
    DraweeController controller = Fresco.newDraweeControllerBuilder()
            .setOldController(imageView.getController())
            .setImageRequest(imageRequestBuilder.build())
            .build();
    
    imageView.setHierarchy(hierarchy);
    imageView.setController(controller);
    
    if(isSvg) {
        imageView.setLayerType(View.LAYER_TYPE_SOFTWARE,null);
    }
}

3. Clean Up Resources Properly

Make sure you release Fresco resources when views are no longer needed (e.g., in fragment onDestroyView or activity onDestroy):

// In your fragment or activity
@Override
public void onDestroyView() {
    super.onDestroyView();
    if (imageView != null) {
        imageView.setController(null);
    }
}

Why These Changes Work

  • Disabling network and disk cache removes unused components that waste memory.
  • Shrinking the memory cache ensures Fresco doesn't hoard more memory than necessary for your local image use case.
  • Reusing hierarchies cuts down on object creation and reduces garbage collection overhead.
  • Downsampling makes Fresco load a smaller, more efficient bitmap that fits your ImageView's exact size.

Give these tweaks a try, and you should see Fresco's memory usage drop to match (or even beat) your previous caching mechanism!

内容的提问来源于stack exchange,提问作者Piyush

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:37:32