欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android Intent传递数据大小限制详解

程序员文章站 2022-06-14 17:42:36
前言 在sendbroadcast,startactivity时,我们会用到intent。 intent可以携带一些数据,比如基本类型数据int、boolean,或...

前言

在sendbroadcast,startactivity时,我们会用到intent。

intent可以携带一些数据,比如基本类型数据int、boolean,或是string,或是序列化对象,parcelable与serializable。
intent传递数据时,如果数据太大,可能会出现异常。比如app闪退,或是intent发送不成功,logcat报错等等。

这就牵涉到一个问题:intent 传递数据大小限制。

intent到底能够携带多少数据呢?

使用intent传送数据时,可能会出现异常

在intent中传入一个parcelable对象;例如传入一个bitmap对象。

代码参考: github.com/rustfisher/

  bitmap b1 = bitmap.createscaledbitmap(srcbmp, dstwid, dstheight, false);
  intent intent = new intent(msg_intent);
  intent.putextra(k_pic, b1);

选择bitmap的原因是,bitmap实现了parcelable接口,并且可以通过getbytecount()得知所占内存大小。

sendbroadcast时,报出如下信息

 v/activitymanager: broadcast: intent { act=intent_bi flg=0x10 (has extras) } ordered=false userid=0 callerapp=processrecord{27aeaaf5 31217:com.rustfisher.basic4/u0a113}
 e/javabinder: !!! failed binder transaction !!!
 w/broadcastqueue: failure sending broadcast intent { act=intent_bi flg=0x10 (has extras) }
        android.os.transactiontoolargeexception
            at android.os.binderproxy.transactnative(native method)
            at android.os.binderproxy.transact(binder.java:504)
            at android.app.applicationthreadproxy.scheduleregisteredreceiver(applicationthreadnative.java:1170)
            at com.android.server.am.broadcastqueue.performreceivelocked(broadcastqueue.java:576)
            at com.android.server.am.broadcastqueue.delivertoregisteredreceiverlocked(broadcastqueue.java:848)
            at com.android.server.am.broadcastqueue.processnextbroadcast(broadcastqueue.java:917)
            at com.android.server.am.broadcastqueue$broadcasthandler.handlemessage(broadcastqueue.java:254)
            at android.os.handler.dispatchmessage(handler.java:111)
            at android.os.looper.loop(looper.java:194)
            at android.os.handlerthread.run(handlerthread.java:61)
            at com.android.server.servicethread.run(servicethread.java:46)

查看异常类transactiontoolargeexception,它继承了remoteexception

package android.os;
public class transactiontoolargeexception extends remoteexception {
  public transactiontoolargeexception() {
    super();
  }

  public transactiontoolargeexception(string msg) {
    super(msg);
  }
}

追踪到binder,它的transactnative方法会报出remoteexception

public native boolean transactnative(int code, parcel data, parcel reply,
      int flags) throws remoteexception;

抛出异常与binder有关。

intent携带信息的大小受binder限制

intent携带信息的大小其实是受binder限制。本文标题也可以改为“binder传递数据大小限制”。

数据以parcel对象的形式存放在binder传递缓存中。

如果数据或返回值比传递buffer大,则此次传递调用失败并抛出transactiontoolargeexception异常。

binder传递缓存有一个限定大小,通常是1mb。但同一个进程中所有的传输共享缓存空间。

多个地方在进行传输时,即时它们各自传输的数据不超出大小限制,transactiontoolargeexception异常也可能会被抛出。

在使用intent传递数据时,1mb并不是安全上限。因为binder中可能正在处理其它的传输工作。

不同的机型和系统版本,这个上限值也可能会不同。

在其它地方,例如onsaveinstancestate(@nonnull bundle outstate),也可能会遇到与binder有关的。

为什么binder要限制传输数据的大小

个人推测,作为一种ipc的方式,binder并不是为传输大量数据而设计。

传输大量数据,可以考虑url之类的方法。

参考

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。