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




