Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2019-09-20:Intent传输数据的大小有限制吗?如何解决? #151

Open
Moosphan opened this issue Sep 20, 2019 · 9 comments
Open
Labels

Comments

@Moosphan
Copy link
Owner

No description provided.

@zoushaohua
Copy link

有限制,1M左右,不同机型大小不同,要问怎么解决,那就是不用(* ̄rǒ ̄)

@chsmy
Copy link

chsmy commented Sep 20, 2019

Intent传输数据的大小受Binder的限制,上限是1M。不过这个1M并不是安全的上限,Binder可能在处理别的工作,安全上限是多少这个在不同的机型上也不一样。

传 512K 以下的数据的数据可以正常传递。
传 512K~1024K 的数据有可能会出错,闪退。
传 1M以上的数据会报错:TransactionTooLargeException
考虑到 Intent 还包括要启动的 Activity 等信息,实际可以传的数据略小于 512K

解决办法

  1. 减少传输数据量
  2. Intent通过绑定一个Bundle来传输,这个可以超过1M,不过也不能过大
  3. 通过内存共享,使用静态变量或者使用EventBus等类似的通信工具
  4. 通过文件共享

@canyie
Copy link

canyie commented Sep 20, 2019

有,限制大约是1M左右,这个限制是binder底层的限制,因为binder本来就没有设计成传输大量数据的
解决办法:别直接传,比如通过MemoryFile开辟一片共享内存,然后传递FileDescriptor,接收端用这个fd读

@Alex-Cin
Copy link

Alex-Cin commented Sep 20, 2019

Intent 中的 Bundle 是使用 Binder 机制进行数据传送的, 数据会写到内核空间, Binder 缓冲区域;
Binder 的缓冲区是有大小限制的, 有些 ROM 是 1M, 有些 ROM 是 2M;
这个限制定义在 frameworks/native/libs/binder/processState.cpp 类中, 如果超过这个限制, 系统就会报错;

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

因为 Binder 本身就是为了进程间频繁-灵活的通信所设计的, 并不是为了拷贝大量数据;
如果非 ipc 就很简单了, static 变量, eventBus 之类的都可以;
如果是 ipc, 一定要一次性传大文件, 可以用 file 或者 socket;

我以前回答过类似的问题
参见 #19

@liupang
Copy link

liupang commented Sep 26, 2019

有限制,一般是 1M,ROM厂商可以修改这个值,但是实际传输上要低于 1M ,因为 intent 一般还要承担其他责任,会占用一部分空间。
非 IPC
EventBus,静态变量都能解决。
IPC
使用文件,Sokect等手段

@huazidev
Copy link

huazidev commented Jun 9, 2020

先说结论:

有大小限制

再说原因:

Intent 是消息传递对象,用于各组件间通信。各组件以及个程序间通信都用到了进程间通信。因此 Intent 的数据传递是基于 Binder 的,Intent 中的数据会存储在 Bundle 中,然后 IPC 过程中会将各个数据以 Parcel 的形式存储在 Binder 的事物缓冲区(Binder transaction buffer)进程传递,而 Binder 的事物缓冲区有个固定的大小,大小在 1M 附近。因为这 1M 大小是当前进程共享的,Intent 中也会带有其他相关的必要信息,所以实际使用中比这个数字要小很多。

解决方式:

  1. 降低传递数据的大小,或考虑其他方式,见2;
  2. IPC: 将大数据缓存到文件,或者存入数据库,或者图片使用 id 等;使用 Socket;
  3. 非 IPC:可以考虑共享内存,EventBus 等

@Justson
Copy link

Justson commented Jul 1, 2020

flying-pigeon 匿名内存

@gs666
Copy link

gs666 commented Aug 28, 2020

平时我们在 Android 组件之间传递数据一般使用Intent都能解决,但是在传递的数据较大时(比如一个size>1000的列表),Intent就不能用了,如果非要用的话就会崩溃:TransactionTooLargeException。Intent 无法传递大数据是因为其内部使用了 Binder 通信机制,Binder 事务缓冲区限制了传递数据的大小。Binder 事务缓冲区的大小限定在 1MB,但是这个尺寸是共享的,也就是并不是传递 1MB 以下的数据就绝对安全,要视当前的环境而定。

不要挑战 Intent 传递数据大小的极限,对于大数据,例如长字符串、Bitmap 等,不要考虑 Intent 传递数据的方案。下面介绍几种解决方案。

使用单例
代码如下,比较简单,在此就不再多介绍了,只需要在传递时 set,在获取时 get。

public class MusicListHolder {

private ArrayList musicInfoList;

public ArrayList getMusicInfoList() {

return musicInfoList;

}

public void setMusicInfoList(ArrayList musicInfoList) {

this.musicInfoList = musicInfoList;

}

private static final MusicListHolder holder = new MusicListHolder();

public static MusicListHolder getInstance() {

return holder;

}

}
注意事项:这种方法不可用于多进程,因为不同的进程获取到的单例并非同一个单例,也就是获取不到数据。

使用EventBus
EventBus 是一个 Android 端优化的 Publish/subscribe 消息总线,简化了应用程序内各个组件间、组件与后台线程间的通信。在《阿里巴巴Android开发手册》中也有推荐:“Activity 间的数据通信,对于数据量比较大的,避免使用 Intent + Parcelable 的方式,可以考虑 EventBus 等替代方案,以免造成 TransactionTooLargeException。”。具体使用可参见:EventBus

使用 Application
将数据保存在Application中,用的时候取出来。这样整个应用都能够读写这个数据。使用很方便,在此就不多讲了。但是使用时是有一些问题的要注意的。

有时候因为内存不足等原因,我们的应用会被系统强制杀死,此时再次点击进入应用时,系统会直接进入被杀死前的那个界面。但是此时Application却是新创建的,我们也就无法拿到之前存取的数据,如果不加以判断,则会导致空对象的问题。

使用建议:

使用时一定要做好非空判断
如果数据为空,可以考虑逻辑上让应用直接返回到最初的Activity。
持久化数据
将数据保存在文件里。常见的手段有sqlite、shared preference、file等。

优点:

应用中所有地方都可以访问
不会轻易丢失
缺点:

操作麻烦
效率低下
读取易出错

@mlinqirong
Copy link

Intent的上限是1M
传递521K的数据为正常
传递512K-1024K的数据可能会报错
传递大于1024K的数据就会报错
解决方法
减少传递数量
传递数据使用绑定Bundle 这个可以超过1M 但也不能太大
使用EventBus传递
数据保存 文件保存方式

@b1tb1t
Copy link

b1tb1t commented Jan 24, 2024

通过putBinder的方式,利用共享内存

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests