不止是“搬家具”:构建面向“作用域”的 Android 大数据传递架构

236 阅读4分钟

一句话总结:

解决大数据传递问题的关键,是首先明确数据的“作用域”。应用内部的传递,应首选 ViewModel 和 Repository 架构;而跨进程的共享,则应采用现代的 SharedMemory 机制。


第一步:重新定义问题——你的数据要“搬”到哪里去?

在选择“搬家工具”之前,我们必须先回答两个核心问题:

  1. 数据传递的作用域是? 是在同一个 App 内部(Intra-Process),还是需要跨越 App 的边界(Inter-Process)?
  2. 数据的生命周期是? 数据是一次性的瞬时传递,还是需要在多个地方被缓存和复用?

根据这两个问题的答案,我们可以绘制出一张清晰的决策地图。


场景一:“户内搬运”——同一个应用内的数据传递 (Intra-Process)

当你在应用的 Activity、Fragment 之间传递数据时,所有组件都运行在同一个进程中。此时,我们有最高效、最安全的架构方案。

情况 A: 瞬时数据传递(把客厅的数据带到卧室)

  • 需求: 将一个屏幕的数据(如用户填写的数据对象)传递给下一个屏幕。

  • 最佳方案:使用 ViewModel

    • ViewModel 的生命周期长于 Activity/Fragment,能在屏幕旋转等配置变更后存活。将数据保存在 ViewModel 中,新的 UI 组件可以直接从中获取,无需通过 Intent 传递,避免了序列化和大小限制。
    • 这是 Jetpack 架构下的“标准答案”,它从根本上解决了进程内的数据共享问题。

情况 B: 缓存与复用(把常用物品放在公共储物柜)

  • 需求: 缓存从网络或数据库加载的数据(如用户信息、配置),供 App 内多个页面使用。

  • 最佳方案:Repository + LRUCache

    • 在这里,LRUCache 终于找到了它正确的位置——作为数据仓库 (Repository) 内部的内存缓存策略
    • 正确架构: UI 层向 Repository 请求数据,Repository 优先从内部的 LRUCache 中查找,如果未命中,再从网络或数据库加载,并存入缓存。UI 层永远不应直接与 LRUCache 交互。

场景二:“跨国运输”——跨进程数据共享 (Inter-Process)

当数据需要从你的 App 发送到另一个 App、一个独立的 Service 进程,或者反之时,我们必须使用真正的 IPC(跨进程通信)机制。

情况 A: 瞬时、大数据量的传递(空投一个大型集装箱)

  • 需求: 发送一个大型 Bitmap、一段音频数据或一个机器学习模型文件给另一个进程。

  • 最佳方案:现代 SharedMemory API (Android 8.0+)

    • SharedMemory 是官方推荐的、用于跨进程共享大块数据的高性能“零拷贝”方案。它通过传递一个轻量的文件描述符,让多个进程直接映射到同一块物理内存。
    • 这是 Ashmem 技术的现代化、安全且无需反射的实现方式。
    // 发送方:创建、写入并发送 SharedMemory
    val shm = SharedMemory.create("MySharedMemory", 1024 * 1024) // 创建 1MB 共享内存
    val byteBuffer = shm.mapReadWrite()
    byteBuffer.put(largeDataByteArray)
    SharedMemory.unmap(byteBuffer)
    
    // 通过 Binder/Intent 传递 ParcelFileDescriptor
    val pfd = shm.parcelFileDescriptor 
    // intent.putExtra("shm_pfd", pfd)
    
    // 接收方:通过 PFD 映射并读取
    val receivedPfd = // ... 从 Intent/Binder 获取 ...
    val receivedShm = SharedMemory.fromFileDescriptor(receivedPfd)
    val readBuffer = receivedShm.mapReadOnly()
    val receivedData = ByteArray(readBuffer.remaining())
    readBuffer.get(receivedData)
    // ... 使用数据后,记得关闭资源 ...
    

情况 B: 结构化、持久化的数据共享(建立一个标准化的海关口岸)

  • 需求: 向其他应用安全地暴露你的文件、或数据库中的特定数据(如联系人应用)。

  • 最佳方案:ContentProvider

    • 这是 Android 平台官方指定的、用于跨进程共享结构化数据的标准机制。它拥有完善的权限模型和统一的 URI 查询接口,是实现安全、可控的数据共享的唯一正确方式。

四、总结:你的大数据传递决策矩阵

瞬时传递 (Transient)缓存/持久化 (Cached/Persistent)
应用内 (Intra-Process)ViewModelRepository + LRUCache
跨进程 (Inter-Process)SharedMemoryContentProvider (背后可以是文件或数据库)

通过这个矩阵,你可以清晰地看到,LRUCacheSharedMemory (Ashmem) 并非竞争关系,而是分别服务于完全不同架构场景的专属工具。在为你的大数据“搬家”前,请先用这个矩阵定位你的“作用域”,然后选择最高效、最正确的“交通工具”。