android 大图传递如何避免OOM

        在同一个进程内,两个 Activity 之间传递大图,面临着和跨进程通信(IPC)一模一样的致命红线:TransactionTooLargeException。这是因为,当你使用 Intent.putExtra("bitmap", bitmap) 时,系统底层依然会使用 Binder 传输机制将数据拷贝到系统进程。而系统为每个应用分配的 Binder 缓存区只有大约 1MB 且是全局共享的。如果你的图库应用中,用户点击一张 5M 或更高分辨率的手机照片,直接用 Intent 传 Bitmap 会瞬间引发线上直接闪退。

一、同一进程传递大数据

1. 使用内存全局单例缓存桥接

既然两个 Activity 运行在同一个进程(JVM 堆内存共享)中,最完美的做法就是:不要把图片放进 Intent,只在 Intent 里传递一个轻量级的字符串(Key),图片数据暂存在内存单例中。

建立内存桥接

import android.graphics.Bitmap

object ImageBridge {
    // 使用 HashMap 暂存大图,支持同时处理多个转场大图
    private val imageCache = HashMap<String, Bitmap>()
    private const val IMAGE_KEY = "gallery_image_key_"

    /**
     * 将大图存入内存桥接仓,并返回一个唯一 Key
     */
    fun putImage(bitmap: Bitmap): String {
        val key = "$IMAGE_KEY${System.currentTimeMillis()}"
        imageCache[key] = bitmap
        return key
    }

    /**
     * 取出大图,并自动将其从缓存中抹除,防止内存泄漏
     */
    fun popImage(key: String?): Bitmap? {
        if (key == null) return null
        return imageCache.remove(key) // remove 会返回对应的值并从 map 中彻底干掉
    }

}

发起跳转页面

   val intent = Intent(this@MainActivity, SharedMemoryActivity::class.java)
            val bitmap = BitmapFactory.decodeResource(resources, R.drawable.aa)
            val imageKey = putImage(bitmap)
            intent.putExtra("KEY_IMAGE_BRIDGE", imageKey)
            startActivity(intent)

接收数据页面

       val imageKey = intent.getStringExtra("KEY_IMAGE_BRIDGE")
        val largeBitmap = ImageBridge.popImage(imageKey)
        LogUtils.d(TAG, "largeBitmap width=${largeBitmap?.width}  height =${largeBitmap?.height}")

2.使用路径传递

将图片数据保存到应用目录下,再拿保存的路径去听过intent去传递

suspend fun saveBitmapToCache(context: Context, bitmap: Bitmap): String? = withContext(
        Dispatchers.IO
    ) {
        // 1. 在 cache 目录下建立临时中转沙盒文件
        val cacheDir = File(context.cacheDir, "image_bridge")
        if (!cacheDir.exists()) {
            cacheDi
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

踏雪羽翼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值