探究Intent数据传输大小限制

引入

  
在使用Intent传输数据的时候,数据大小超过1M就会报错。
崩溃异常:

  
Exception: TransactionTooLargeException


  
接下来来分析下为什么页面数据传输会有这个量的限制以及这个限制的大小具体是多少。

  1. 道Context和Activity都含有startActivity,但两者最终都调用了Activity中的startActivity;
  2. 而startActivity最终会调用自身的startActivityForResult;
  3. 然后系统会调用Instrumentation中的execStartActivity方法;
  4. 接着调用了ActivityManger.getService().startActivity ,getService返回的是系统进程中的AMS在app进程中的binder代理;

其实就是App进程调用AMS进程中的方法了。就是系统进程和app应用进程间的数据交互了。所以Intent的数据都要带入AMS,就是Binder通信了。

探究Intent数据大小限制,就是弄清楚Binder的数据传输问题。

Binder实现数据通信:通过Copy_from_User从用户空间将数据拷贝到内核空间,内核空间的内存和Service服务端的内存通过mmap()映射共享。所以原因就在此:

普通的由Zygote孵化而来的用户进程,所映射的Binder内存大小是不到1M的,准确说是 110241024) - (4096 *2) :这个限制定义在/processState.cpp类中,如果传输说句超过这个大小,系统就会报错,因为Binder本身就是为了进程间频繁而灵活的通信所设计的,并不是为了拷贝大数据而使用的,在内核中,其实也有个限制,是4M。

#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))

总结

  
intent携带的数据会经过Binder内核再传递到目标Activity中去,因为binder映射内存的限制,所以startActivity也就会这个限制了。

解决方案

  
一、写入临时文件或者数据库,通过FileProvider将该文件或者数据库通过Uri发送至目标。一般适用于不同进程,比如分离进程的UI和后台服务,或不同的App之间。之所以采用FileProvider是因为7.0以后,对分享本App文件存在着严格的权限检查。

  
二、通过设置静态类中的静态变量进行数据交换。一般适用于同一进程内,这样本质上数据在内存中只存在一份,通过静态类进行传递。需要注意的是进行数据校对,以防多线程操作导致的数据显示混乱。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 当我们用Intent传输大数据时,有可能会出现错误: 如上我们传递了1M大小的数据时,结果程序就一直反复报如下Tr...
    大头呆阅读 4,321评论 1 8
  • 2.1 Activity 2.1.1 Activity的生命周期全面分析 典型情况下的生命周期:在用户参与的情况下...
    AndroidMaster阅读 3,110评论 0 8
  • 本笔记整理自: https://www.gitbook.com/book/tom510230/android_...
    01_小小鱼_01阅读 1,062评论 0 4
  • 之前有写过一篇笔记《Android温故而知新 - AIDL》从应用层分析了aidl的数据是怎么传递的,还有一篇《A...
    嘉伟咯阅读 2,256评论 7 9
  • 今天我遇见了两件事,感觉父母的爱和老师的爱是多么的重要,第一件事情是我的嫂子第一次被学校叫去,是因为孩子发生...
    琦赟阅读 362评论 0 1