在同一个进程内,两个 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