两个Activity跳转,我们一般会用Intent传递数据,但如果传递数据太大会出现如下异常:

2020-10-23 09:52:22.142 5506-5506 E/AndroidRuntime: FATAL EXCEPTION: main
    Process: jdlf_scgl_zp_android.ui.m990_system, PID: 5506
    java.lang.RuntimeException: Failure from system
        at android.app.Instrumentation.execStartActivity(Instrumentation.java:1525)
        at android.app.Activity.startActivityForResult(Activity.java:4226)
        at android.app.Activity.startActivityForResult(Activity.java:4185)
        at jdlf_scgl_zp_android.ui.m039_ui_mat_distribution.MatDistributionManager.PickListManager.PickListToLightOperateActivity.jumpToMoveWare(PickListToLightOperateActivity.java:426)
        at jdlf_scgl_zp_android.ui.m039_ui_mat_distribution.MatDistributionManager.PickListManager.PickListToLightOperateActivity.onClick(PickListToLightOperateActivity.java:165)
        at jdlf_scgl_zp_android.ui.m039_ui_mat_distribution.MatDistributionManager.PickListManager.-$$Lambda$qSbxt2tr_nrJz4nnSCo7yUGOiUU.onClick(lambda)
        at android.view.View.performClick(View.java:5675)
        at android.view.View$PerformClick.run(View.java:22641)
        at android.os.Handler.handleCallback(Handler.java:836)
        at android.os.Handler.dispatchMessage(Handler.java:103)
        at android.os.Looper.loop(Looper.java:203)
        at android.app.ActivityThread.main(ActivityThread.java:6251)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)
     Caused by: android.os.TransactionTooLargeException: data parcel size 2435216 bytes
        at android.os.BinderProxy.transactNative(Native Method)
        at android.os.BinderProxy.transact(Binder.java:622)
        at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:3191)
        at android.app.Instrumentation.execStartActivity(Instrumentation.java:1518)
        at android.app.Activity.startActivityForResult(Activity.java:4226) 
        at android.app.Activity.startActivityForResult(Activity.java:4185) 
        at jdlf_scgl_zp_android.ui.m039_ui_mat_distribution.MatDistributionManager.PickListManager.PickListToLightOperateActivity.jumpToMoveWare(PickListToLightOperateActivity.java:426) 
        at jdlf_scgl_zp_android.ui.m039_ui_mat_distribution.MatDistributionManager.PickListManager.PickListToLightOperateActivity.onClick(PickListToLightOperateActivity.java:165) 
        at jdlf_scgl_zp_android.ui.m039_ui_mat_distribution.MatDistributionManager.PickListManager.-$$Lambda$qSbxt2tr_nrJz4nnSCo7yUGOiUU.onClick(lambda) 
        at android.view.View.performClick(View.java:5675) 
        at android.view.View$PerformClick.run(View.java:22641) 
        at android.os.Handler.handleCallback(Handler.java:836) 
        at android.os.Handler.dispatchMessage(Handler.java:103) 
        at android.os.Looper.loop(Looper.java:203) 
        at android.app.ActivityThread.main(ActivityThread.java:6251) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1063) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924) 

关键异常信息是这两行:

java.lang.RuntimeException: Failure from system
Caused by: android.os.TransactionTooLargeException: data parcel size 2435216 bytes

其实很早我就知道这个结论,但是印象中没有遇到过这个问题。最近突然遇见了几次这个问题,原因都还不一样:

  1. 自定义签名页面签完名后,将签名生成一张图片,然后将图片的Bitmap对象回传给上个页面,因为传递图片传递Bitmap对象,数据量过大;
  2. 传递集合ArrayList,这是我们经常用的,起初不觉得是ArrayList的问题,后面日志一看List中有1200多条数据,序列化的List达到1.5M了;
  3. Activity+Viewpager+Fragment形式将数据传递给Fragment时使用Bundle,而bundle中携带数据量过大。

1、第一种的解决方案是把bitmap存储为byte数组,然后再通过Intent传递:

 ByteArrayOutputStream baos = new ByteArrayOutputStream();
 mBitmap.compress(Bitmap.CompressFormat.JPEG, 50, baos);
 byte[] bytesArrayBmp = baos.toByteArray();
 intent.putExtra(SIGN_PIC_BITMAP, bytesArrayBmp);

那么为什么将 Bitmap 转化为一个 byte 数组就可以传递了呢,我个人的理解是,Bitmap实现了Parcelable序列化接口,所以传递的时候会将Bitmap的全部数据序列化到内存中,所以会超出1M限制。byte数组在内存中对应的是地址值,传递的时候其实是地址值的传递,所以不会超出限制。作者的第二种方法传递map对象(或者其他人说的HashMap)也是传递的内存中的地址值,和传递byte数组严格来说是一样的。

2、第二种的情况:数据保存到本地存储中,在目标Activity中再提取出来。

3、第三种需要在获取数据之后使用bundle.clear()方法清空bundle;

Bundle bundle = getArguments();
//获取解析结果集
//String strAsModel = bundle.getString("fdModelList");
//获取数据之后要清空bundle,否则数据量大时跳转到其他Activity会报异常
bundle.clear();

当然目前我在项目中已经杜绝Activity往Fragment中传递大数据,需要的数据直接在Fragment中获取。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐