インテント転送データサイズ制限の問題:android.os.TransactionTooLargeException:データパーセルサイズxxxxxxxバイト

2つのアクティビティジャンプ。通常、インテントを使用してデータを渡しますが、渡されたデータが大きすぎると、次の例外が発生します。

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) 

重要な例外情報は次の2行です。

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

実際、私はこの結論を非常に早く知っていましたが、私の印象ではこの問題に遭遇したことはありませんでした。私は最近この問題に何度か遭遇しましたが、理由はまだ異なります。

  • ユーザー定義の署名ページが署名されると、画像に署名して前のページに送り返します。ビットマップオブジェクトが画像を通過するため、データ量が多すぎます。
  • コレクションArrayListを渡すために、これは私たちがよく使用するものです。最初は、ArrayListに問題があるとは思いませんでした。ログを確認したところ、リストには1200を超えるデータがあり、シリアル化されたリストに到達しました。 1.5M;
  • Activity + Viewpager + Fragmentフォームは、データをFragmentに転送するときにバンドルを使用し、バンドルで運ばれるデータの量が多すぎます。

1.最初の解決策は、ビットマップをバイト配列として格納し、それをインテントに渡すことです。

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

では、なぜビットマップをバイト配列に転送できるのでしょうか?私の個人的な理解では、ビットマップはパーセル可能なシリアル化インターフェイスを実装しているため、転送時にビットマップのすべてのデータがメモリにシリアル化されるため、1Mの制限を超えます。バイト配列はメモリ内のアドレス値に対応し、渡されると実際にはアドレス値になるため、制限を超えることはありません。マップオブジェクト(または他の人が呼ぶHashMap)を渡す作成者の2番目の方法も、渡されたメモリ内のアドレス値であり、バイト配列を渡すのと厳密に同じです。

2. 2番目のケース:データはローカルストレージに保存され、ターゲットアクティビティから抽出されます。

3. 3番目は、bundle.clear()メソッドを使用して、データを取得した後にバンドルをクリアする必要があります。

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

もちろん、このプロジェクトでは、ビッグデータをフラグメントに渡すためのアクティビティをすでに終了しており、必要なデータはフラグメントで直接取得されます。

おすすめ

転載: blog.csdn.net/beita08/article/details/109237173