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

Android拍照存SQLite报错:Can't compress a recycled bitmap

Fixing "Can't compress a recycled bitmap" When Saving Camera Photos to SQLite

Hey there, let's tackle this super frustrating issue you're facing—nothing's more annoying than chasing a recycled bitmap error when you can't spot where the recycle() call is happening! Let's break down the root cause and actionable fixes:

Core Issue Breakdown

This error pops up because the Bitmap object you're trying to compress with compress() has already been recycled (either via an explicit recycle() call in your code, or automatically by the Android system due to memory constraints). Once a bitmap is recycled, it's no longer usable for any operations like compression.

Step-by-Step Fixes & Debugging Tips

1. Stop Using the Original Camera Bitmap Directly

The thumbnail bitmap returned by data.getParcelableExtra("data") (from the camera intent) is often managed by the system, and might get recycled before you finish processing it. Instead, create a copy of the bitmap to work with:

Bitmap originalBitmap = data.getParcelableExtra("data");
if (originalBitmap != null && !originalBitmap.isRecycled()) {
    // Create a mutable copy to avoid relying on the system-managed bitmap
    Bitmap workingBitmap = originalBitmap.copy(originalBitmap.getConfig(), true);
    
    // Compress the copy into a byte array for SQLite
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    workingBitmap.compress(Bitmap.CompressFormat.JPEG, 80, stream);
    byte[] imageBytes = stream.toByteArray();
    
    // Save imageBytes to your SQLite database here
    
    // Clean up: recycle the copy first, then the original
    if (!workingBitmap.isRecycled()) workingBitmap.recycle();
    if (!originalBitmap.isRecycled()) originalBitmap.recycle();
}

2. Fix Asynchronous Operation Timing

If you're using async tasks (Coroutines, AsyncTask, etc.) to handle SQLite inserts, you might be recycling the bitmap on the main thread before the async compression finishes.

  • Always pass the bitmap copy (not the original) to your async task.
  • Never recycle the bitmap until after the compression and database insert are fully complete.

3. Avoid Implicit System Recycling

Large camera photos are prime targets for system recycling when memory is low. Reduce memory pressure and prevent this:

  • Load the full-size image from its file path (instead of using the camera's thumbnail) with downsampling to shrink it:
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inSampleSize = 4; // Shrink image to 1/4 its original size (adjust as needed)
    Bitmap downsampledBitmap = BitmapFactory.decodeFile(photoFile.getAbsolutePath(), options);
    
  • Convert the bitmap to a byte array immediately after loading, then recycle the bitmap right away—don't hold onto the bitmap object longer than necessary.

4. Check Third-Party Image Libraries

If you're using Glide, Picasso, or similar libraries to display the camera photo, these libraries automatically recycle bitmaps to save memory.

  • Don't reuse the bitmap that the library loaded into an ImageView. Instead, reload the image directly from its source (file path or URI) to get a fresh bitmap for compression.

5. Track Down Hidden recycle() Calls

To find where the bitmap is being recycled:

  • Add log statements everywhere you explicitly call bitmap.recycle() to track when it happens.
  • Use Android Studio's Memory Profiler to monitor the bitmap's lifecycle—you can see exactly when it's marked for recycling.
  • If you're using any custom view or utility class that handles bitmaps, double-check those for unintended recycle() calls.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:30:10