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

从ActiveAndroid数据库获取ImageList时触发OutOfMemory Error

解决ActiveAndroid查询图片列表时的OutOfMemoryError问题

看起来你已经搞定了拍照后的OOM问题,但在从ActiveAndroid加载未上传图片列表时又栽了跟头——而且这个OOM是在Cursor解析字符串的时候触发的,从错误日志看,系统尝试分配422KB内存但只剩335KB可用,这说明你的ImageUploadModel里存储的图片相关数据(大概率是Base64格式的图片内容或者完整的二进制数据)太大,一次性加载多条记录时,CursorWindow要把这些大字符串全部加载到内存里,直接撑爆了。

给你几个针对性的解决方案,按优先级排序:

1. 改用文件路径存储(最推荐)

不要再把完整的图片数据存在数据库里,而是将图片保存到内部存储后,把文件的绝对路径存在ImageUploadModel中。这样数据库里只存短字符串路径,加载列表时内存占用可以忽略不计,需要上传或显示图片时,再通过路径去读取文件。

代码调整示例:

修改ImageUploadModel的字段:

public class ImageUploadModel extends Model {
    // 替换原来的imageData(Base64或二进制字段)
    public String imagePath;
    // 其他字段...
    public String intimationId;
    public boolean isImageDetailsUpload;
}

查询时就不会加载大体积数据,自然不会OOM:

public static List<ImageUploadModel> getUnUploadedImageListonintimation(String IntimationId) {
    return new Select()
            .from(ImageUploadModel.class)
            .where("intimationId=?", IntimationId)
            .where("isImageDetailsUpload=?", false)
            .execute();
}

2. 分批分页加载数据

如果暂时无法修改存储方式,那就不要一次性加载所有未上传图片,改用分页查询,每次只加载少量记录(比如10条),处理完这批再加载下一批。

代码调整示例:

修改查询方法支持分页:

public static List<ImageUploadModel> getUnUploadedImageListonintimation(String IntimationId, int offset, int limit) {
    return new Select()
            .from(ImageUploadModel.class)
            .where("intimationId=?", IntimationId)
            .where("isImageDetailsUpload=?", false)
            .offset(offset)
            .limit(limit)
            .execute();
}

在后台服务中循环加载:

int limit = 10;
int offset = 0;
List<ImageUploadModel> batch;
do {
    batch = ImageUploadModel.getUnUploadedImageListonintimation(uploadImageModel.getIntimationId(), offset, limit);
    // 处理当前批次的图片
    processImages(batch);
    offset += limit;
} while (!batch.isEmpty());

3. 延迟加载大字段

如果必须在数据库中保留图片数据,可以在列表加载时只查询必要的元数据(比如ID、intimationId、上传状态),不加载图片字段。等到需要使用图片数据时,再单独查询该条记录的图片字段。

代码调整示例:

public static List<ImageUploadModel> getUnUploadedImageMetadata(String IntimationId) {
    List<ImageUploadModel> list = new ArrayList<>();
    Cursor cursor = null;
    try {
        // 只查询需要的字段,排除大体积的imageData
        String query = "SELECT id, intimationId, isImageDetailsUpload FROM ImageUploadModel WHERE intimationId=? AND isImageDetailsUpload=?";
        cursor = SQLiteDatabase.openDatabase(ActiveAndroid.getDatabase().getPath(), null, SQLiteDatabase.OPEN_READONLY)
                .rawQuery(query, new String[]{IntimationId, "0"});
        
        while (cursor.moveToNext()) {
            ImageUploadModel model = new ImageUploadModel();
            model.setId(cursor.getLong(cursor.getColumnIndex("id")));
            model.setIntimationId(cursor.getString(cursor.getColumnIndex("intimationId")));
            model.setIsImageDetailsUpload(cursor.getInt(cursor.getColumnIndex("isImageDetailsUpload")) == 1);
            list.add(model);
        }
    } finally {
        if (cursor != null) {
            cursor.close();
        }
    }
    return list;
}

// 当需要图片数据时,单独查询
public static ImageUploadModel getImageModelWithData(long modelId) {
    return new Select().from(ImageUploadModel.class).where("id=?", modelId).executeSingle();
}

4. 再次优化图片压缩

检查你当前的图片压缩逻辑,确保压缩后的图片尺寸和质量已经足够小——比如上传用的图片不需要和原始拍照尺寸一样大,可以压缩到1080p以内,质量调到70%左右,进一步减少单条记录的数据体积。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:37:26