You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android中E/JavaBinder: FAILED BINDER TRANSACTION错误排查求助

Hey,这个问题我之前做项目时也踩过坑,结合你的描述和错误日志给你理清楚:

错误原因

你看到的TransactionTooLargeException本质是Android Binder进程间通信的大小限制导致的。当你的应用退到后台时,系统会调用onSaveInstanceState来保存页面状态,这个方法里的Bundle会通过Binder传递给系统的ActivityManager服务。而Binder有一个默认的传输上限(大概1MB左右),你的日志里显示parcel size是539984字节,已经接近这个阈值了,所以触发了崩溃。

你说自己的onStop()没做操作,onSaveInstanceState里的Bundle是空,但移除最大的ArrayList就没问题——这大概率是因为这个大ArrayList被间接序列化到了Bundle里:可能是你的Fragment/Activity里的某个组件(比如绑定了数据的RecyclerView、自定义View)在自动保存状态时,把关联的数据集带进去了;或者是你某个持有这个ArrayList的对象被系统默认的状态保存机制给序列化了。

解决方案

给你几个可行的解决方向,按优先级排序:

  • 用ViewModel存储大数据集
    ViewModel的生命周期独立于Activity/Fragment的前台后台状态,即使应用退到后台,ViewModel里的数据也不会被销毁,完全不需要通过onSaveInstanceState来保存。你可以把那5个ArrayList都放到ViewModel里,这样既不会触发Binder传输限制,也能在页面恢复时直接拿到数据。

  • 把大集合持久化到本地
    如果ViewModel不适用(比如需要长期保存数据),可以把大ArrayList序列化后存到本地:

    • 用Room数据库:适合结构化数据,存取高效还能支持查询
    • 写JSON文件到内部存储:用Gson/Jackson把ArrayList转成JSON字符串,存到私有文件里,恢复时再解析回来
    • 别用SharedPreferences存大集合,它本身就不适合存储大量数据,容易导致ANR
  • 精简onSaveInstanceState的内容
    重写onSaveInstanceState时,只存最必要的小状态(比如当前选中的列表位置、筛选条件等),不要存整个数据集。另外,如果某些View的自动状态保存没用,可以给它们设置android:saveEnabled="false",避免系统偷偷把不必要的数据塞进Bundle。

  • 兜底方案:捕获异常(不推荐)
    如果以上方法都来不及调整,可以在Activity的onStop或者onSaveInstanceState里捕获这个异常,避免崩溃,但这样会丢失页面状态,只能作为临时过渡方案:

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        try {
            super.onSaveInstanceState(outState);
        } catch (TransactionTooLargeException e) {
            // 这里可以加日志记录,或者做一些降级处理
            e.printStackTrace();
        }
    }
    

附上你提供的错误日志:

01-25 13:51:09.272 4940-4940/com.cathedralsw.schoolteacher E/JavaBinder: !!! FAILED BINDER TRANSACTION !!! (parcel size = 539984)
--------- beginning of crash
01-25 13:51:09.281 4940-4940/com.cathedralsw.schoolteacher E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.cathedralsw.schoolteacher, PID: 4940
java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 539984 bytes
    at android.app.ActivityThread$StopInfo.run(ActivityThread.java:4039)
    at android.os.Handler.handleCallback(Handler.java:761)
    at android.os.Handler.dispatchMessage(Handler.java:98)
    at android.os.Looper.loop(Looper.java:156)
    at android.app.ActivityThread.main(ActivityThread.java:6595)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)
Caused by: android.os.TransactionTooLargeException: data parcel size 539984 bytes
    at android.os.BinderProxy.transactNative(Native Method)
    at android.os.BinderProxy.transact(Binder.java:617)
    at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:3632)
    at android.app.ActivityThread$StopInfo.run(ActivityThread.java:4031)
    at android.os.Handler.handleCallback(Handler.java:761)
    at android.os.Handler.dispatchMessage(Handler.java:98)
    at android.os.Looper.loop(Looper.java:156)
    at android.app.ActivityThread.main(ActivityThread.java:6595)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)
01-25 13:51:09.286 1795-5775/? E/ReportTools: This is not beta user build

内容的提问来源于stack exchange,提问作者Alezis

火山引擎 最新活动