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

Android着色书onPause中PNG Bitmap保存不完整问题求助

问题分析

核心原因是PNG格式的压缩/写入耗时远高于JPEG:

  • 按钮点击时Activity处于活跃状态,后台线程有足够时间完成PNG的完整写入;
  • 但在onPause中,Activity可能很快进入停止/销毁状态,后台线程还没完成PNG写入就被系统终止,导致文件损坏、仅保存部分内容。
    另外,colourImageView.getmBitmap()返回的原Bitmap可能在Activity生命周期结束后被回收,进一步导致压缩数据不完整。
解决方案

方案1:使用WorkManager执行持久化后台保存(推荐)

WorkManager能保证任务即使在应用退出后也能完成,适合这种需要可靠持久化的场景:

  1. 添加WorkManager依赖(根据Gradle版本调整):
implementation "androidx.work:work-runtime:2.8.1"
  1. 创建自定义Worker类处理保存逻辑:
public class SaveBitmapWorker extends Worker {
    private static final String KEY_BITMAP_PATH = "bitmap_path";

    public SaveBitmapWorker(@NonNull Context context, @NonNull WorkerParameters params) {
        super(context, params);
    }

    @NonNull
    @Override
    public Result doWork() {
        String tempPath = getInputData().getString(KEY_BITMAP_PATH);
        if (tempPath == null) {
            return Result.failure();
        }
        File tempFile = new File(tempPath);
        Bitmap bitmap = BitmapFactory.decodeFile(tempPath);
        if (bitmap == null) {
            tempFile.delete();
            return Result.failure();
        }

        File saveFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                "savedBitmap1.png");
        try (FileOutputStream fos = new FileOutputStream(saveFile)) {
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
            SharedPreferencesFactory.saveString(getApplicationContext(), "savedBitmap1", saveFile.getPath());
            tempFile.delete(); // 删除临时文件
            bitmap.recycle();
            return Result.success();
        } catch (Exception e) {
            e.printStackTrace();
            tempFile.delete();
            return Result.retry();
        }
    }

    public static OneTimeWorkRequest buildRequest(File tempBitmapFile) {
        Data inputData = new Data.Builder()
                .putString(KEY_BITMAP_PATH, tempBitmapFile.getAbsolutePath())
                .build();
        return new OneTimeWorkRequest.Builder(SaveBitmapWorker.class)
                .setInputData(inputData)
                .build();
    }
}
  1. 修改setSavedBitmap方法,先把Bitmap保存到临时文件,再交给WorkManager:
private void setSavedBitmap(Bitmap finalBitmap) {
    File tempFile = new File(getCacheDir(), "temp_bitmap.png");
    try (FileOutputStream fos = new FileOutputStream(tempFile)) {
        finalBitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
        OneTimeWorkRequest request = SaveBitmapWorker.buildRequest(tempFile);
        WorkManager.getInstance(this).enqueue(request);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

方案2:复制Bitmap后再异步保存(简单临时方案)

通过复制Bitmap,避免原Bitmap被回收导致的写入异常,尽量降低线程被终止的影响:

private void setSavedBitmap(Bitmap finalBitmap) {
    Bitmap copiedBitmap = Bitmap.createBitmap(finalBitmap);
    File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
            "savedBitmap1.png");

    new Thread(new Runnable() {
        public void run() {
            try (FileOutputStream fos = new FileOutputStream(file)) {
                copiedBitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
                SharedPreferencesFactory.saveString(getApplicationContext(), "savedBitmap1", file.getPath());
                copiedBitmap.recycle();
            } catch (Exception e) {
                e.printStackTrace();
                copiedBitmap.recycle();
            }
        }
    }).start();
}

注意:该方案仍存在线程被系统终止的风险,适合对可靠性要求不高的场景。

额外注意事项

  • Android 10及以上可使用Scoped Storage,无需申请WRITE_EXTERNAL_STORAGE权限;低版本需确保已申请该权限;
  • 禁止在onPause中执行阻塞主线程的操作,避免ANR。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 04:18:13