注册

简单教你Intent如何传大数据

前言


最近想不出什么比较好的内容,但是碰到一个没毕业的小老弟问的问题,那就借机说说这个事。Intent如何传大数据?为什么是简单的说,因为这背后深入的话,有很多底层的细节包括设计思想,我也不敢说完全懂,但我知道当你用Intent传大数据报错的时候应该怎么解决,并且简单聊聊这背后所涉及到的东西。


Intent传大数据


平时可能不会发生这种问题,但比如我之前是做终端设备的,我的设备每秒都会生成一些数据,而长时间的话数据量自然大,这时当我跳到另外一个页面使用intent把数据传过去的时候,就会报错


我们调用


intent.putExtra("key", value) // value超过1M

会报错


android.os.TransactionTooLargeException: data parcel size xxx bytes

这里的xxx就是1M左右,告诉你传输的数据大小不能超过1M,有些话咱也不敢乱说,有点怕误人子弟。我这里是凭印象说的,如果有大佬看到我说错,请狠狠的纠正我。


这个错误描述是这么描述,但真的是限死1M吗,说到这个,就不得不提一样东西,Binder机制,先不要跑,这里不会详细讲Binder,只是提一嘴。


说到Binder那就会联系到mmap内存映射,你可以先简单理解成内存映射是分配一块空间给内核空间和用户空间共用,如果还是不好理解,就简单想成分配一块空间通信用,那在android中mmap分配的空间是多少呢?1M-4K。


那是不是说Intent传输的数据超过1M-4K就会报错,理论上是这样,但实际没到这个值,比如0.8M也可能会报错。所以你不能去走极限操作,比如你的数据到了1M,你觉得只要减少点数据,减到8K,应该就能过了,也许你自己测试是正常的,但是这很危险。


所以能不传大数据就不要传大数据,它的设计初衷也不是为了传大数据用的。如果真要传大数据,也不要走极限操作。


那怎么办,切莫着急,请听我慢慢讲。就这个Binder它是什么玩意,它是Android中独特的进程通信的方式,而Linux中进程通信的方式,在Android中同样也适用。进程间通信有很多方式,Binder、管道、共享内存等。为什么会有这么多种通信方式,因为每种通信方式都有自己的特点,要在不同的场合使用不同的通信方式。


为什么要提这个?因为要看懂这个问题,你需要知道Binder这种通信方式它有什么特点,它适合大量的数据传输吗?那你Binder又与我Intent何干,你抓周树人找我鲁迅干嘛~~所以这时候你就要知道Android四大组件之间是用什么方式通信的。


有点扯远了,现在可以来说说结论了,Binder没办法传大数据,我就1M不到你想怎样?当然它不止1M,只是Android在使用时限制了它只能最多用1M,内核的最大限制是4M。又有点扯远了,你不要想着怎么把限制扩大到4M,不要往这方面想。前面说了,不同的进程通信方式,有自己的特点,适用于某些特定的场景。那Binder不适用于传输大数据,我共享内存行不行?


所以就有了解决办法


bundle.putBinder()

有人可能一看觉得,这有什么不同,这在表面上看差别不大,实则内部大大的不同,bundle.putBinder()用了共享内存,所以能传大数据,那为什么这里会用共享内存,而putExtra不是呢?想搞清楚这个问题,就要看源码了。 这里就不深入去分析了,我怕劝退,不是劝退你们,是劝退我自己。有些东西是这样的,你要自己去看懂,看个大概就差不多,但是你要讲出来,那就要看得细致,而有些细节确实会劝退人。所以想了解为什么的,可以自己去看源码,不想看的,就知道这是怎么一回事就行。


那还有没有其它方式呢?当然有,你不懂共享内存,你写到本地缓存中,再从本地缓存中读取行不行?


办法有很多,如果你不知道这个问题怎么解决,你找不到你觉得可行的解决方案,甚至可以通过逻辑通过流程的方式去绕开这个问题。但是你要知道为什么会出现这样的问题,如果你没接触过进程通信,没接触过Binder,让你看一篇文章就能看懂我觉得不切实际,但是至少得知道是怎么一回事。


比如我只说bundle.putBinder()能解决这个问题,你一试,确实能解决,但是不知道为什么,你又怕会不会有其它问题。虽然这篇文章我一直在打擦边球,没有提任何的原理,但我觉得还是能大概让人知道为什么bundle.putBinder()能解决Intent传大数据,你也就能放心去用了。


作者:流浪汉kylin
链接:https://juejin.cn/post/7205138514870829116
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册