Nougat 上的 android.os.TransactionTooLargeException

2023-11-24

我将 Nexus 5X 更新为 Android N,现在当我在其上安装应用程序(调试或发布)时,我会在每个包含附加捆绑包的屏幕转换上收到 TransactionTooLargeException。该应用程序适用于所有其他设备。 PlayStore 上的旧应用程序具有大部分相同的代码,可在 Nexus 5X 上运行。 有人有同样的问题吗?

java.lang.RuntimeException: android.os.TransactionTooLargeException: data parcel size 592196 bytes
   at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3752)
   at android.os.Handler.handleCallback(Handler.java:751)
   at android.os.Handler.dispatchMessage(Handler.java:95)
   at android.os.Looper.loop(Looper.java:154)
   at android.app.ActivityThread.main(ActivityThread.java:6077)
   at java.lang.reflect.Method.invoke(Native Method)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)
Caused by: android.os.TransactionTooLargeException: data parcel size 592196 bytes
   at android.os.BinderProxy.transactNative(Native Method)
   at android.os.BinderProxy.transact(Binder.java:615)
   at android.app.ActivityManagerProxy.activityStopped(ActivityManagerNative.java:3606)
   at android.app.ActivityThread$StopInfo.run(ActivityThread.java:3744)
   at android.os.Handler.handleCallback(Handler.java:751) 
   at android.os.Handler.dispatchMessage(Handler.java:95) 
   at android.os.Looper.loop(Looper.java:154) 
   at android.app.ActivityThread.main(ActivityThread.java:6077) 
   at java.lang.reflect.Method.invoke(Native Method) 
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865) 
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755) 

每当你看到TransactionTooLargeException发生时Activity正在停止过程中,这意味着Activity正在尝试发送其保存的状态Bundles到系统操作系统,以便安全保存以便稍后恢复(在配置更改或进程终止后),但其中一个或多个Bundles它发送的太大了。对于同时发生的所有此类事务,最大限制约为 1MB,即使没有单个事务也可以达到该限制Bundle超过该限制。

这里的罪魁祸首通常是里面保存了太多的数据onSaveInstanceState的任一Activity or any Fragments由主办Activity。通常,当保存特别大的内容(例如Bitmap但当发送大量较小的数据时也可能发生这种情况,例如列表Parcelable对象。 Android 团队已经多次明确表示,只应保存少量与视图相关的数据。onSavedInstanceState。然而,开发人员经常保存网络数据页面,以便使配置更改看起来尽可能顺利,而不必再次重新获取相同的数据。截至 Google I/O 2017,Android 团队已明确表示 Android 应用程序的首选架构会保存网络数据

  • 在内存中,因此可以在配置更改时轻松重用
  • 到磁盘,以便在进程死亡和应用程序会话后可以轻松恢复

他们的新ViewModel框架和Room持久性库旨在帮助开发人员适应这种模式。如果您的问题是在中保存太多数据onSaveInstanceState,使用这些工具更新到这样的架构应该可以解决您的问题。

就我个人而言,在更新到新模式之前,我想采用现有的应用程序并绕过TransactionTooLargeException同时。我写了一个快速库来做到这一点:https://github.com/livefront/bridge。它使用相同的一般思想,即在配置更改时从内存恢复状态以及在进程死亡后从磁盘恢复状态,而不是通过以下方式将所有状态发送到操作系统onSaveInstanceState,但只需要对现有代码进行很少的更改即可使用。不过,任何符合这两个目标的策略都应该帮助您避免异常,而不会牺牲保存状态的能力。

最后要注意的是:您在 Nougat+ 上看到此情况的唯一原因是,最初如果超出活页夹事务限制,则将保存的状态发送到操作系统的过程将默默失败,仅在 Logcat 中显示此错误:

!!!活页夹交易失败!!!

在《牛轧糖》中,这种无声的失败升级为严重的崩溃。值得赞扬的是,这是开发团队记录的内容Nougat 的发行说明:

许多平台 API 现在已经开始检查跨 Binder 事务发送的大型有效负载,并且系统现在将 TransactionTooLargeExceptions 作为 RuntimeExceptions 重新抛出,而不是默默地记录或抑制它们。一个常见的示例是在 Activity.onSaveInstanceState() 中存储过多数据,这会导致当您的应用面向 Android 7.0 时 ActivityThread.StopInfo 抛出 RuntimeException。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Nougat 上的 android.os.TransactionTooLargeException 的相关文章

随机推荐