我得到了一个TransactionTooLargeException。无法复制的。文件里说

The Binder transaction failed because it was too large. During a remote procedure call, the arguments and the return value of the call are transferred as Parcel objects stored in the Binder transaction buffer. If the arguments or the return value are too large to fit in the transaction buffer, then the call will fail and TransactionTooLargeException will be thrown. ... There are two possible outcomes when a remote procedure call throws TransactionTooLargeException. Either the client was unable to send its request to the service (most likely if the arguments were too large to fit in the transaction buffer), or the service was unable to send its response back to the client (most likely if the return value was too large to fit in the transaction buffer). ...

在某个地方,我传递或接收的参数超出了未知的限制。在哪里?

stacktrace没有显示任何有用的东西:

java.lang.RuntimeException: Adding window failed
at android.view.ViewRootImpl.setView(ViewRootImpl.java:548)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:406)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:320)
at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:152)
at android.view.Window$LocalWindowManager.addView(Window.java:557)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2897)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
at android.app.ActivityThread.access$600(ActivityThread.java:139)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1262)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:4977)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.os.TransactionTooLargeException
at android.os.BinderProxy.transact(Native Method)
at android.view.IWindowSession$Stub$Proxy.add(IWindowSession.java:569)
at android.view.ViewRootImpl.setView(ViewRootImpl.java:538)
... 16 more
android.os.TransactionTooLargeException
at android.os.BinderProxy.transact(Native Method)
at android.view.IWindowSession$Stub$Proxy.add(IWindowSession.java:569)
at android.view.ViewRootImpl.setView(ViewRootImpl.java:538)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:406)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:320)
at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:152)
at android.view.Window$LocalWindowManager.addView(Window.java:557)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2897)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
at android.app.ActivityThread.access$600(ActivityThread.java:139)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1262)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:4977)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
at dalvik.system.NativeStart.main(Native Method)

这似乎和观点有关?这与远程过程调用有什么关系?

可能重要的是:Android版本:4.0.3,设备:HTC One X


当前回答

重要的是要理解,无论设备功能或应用程序,事务缓冲区被限制为1mb。这个缓冲区用于你所做的每个API调用,并在应用程序当前运行的所有事务之间共享。

我相信它还包含一些特定的对象,如包裹和such (package . get()),因此始终将每个get()与recycle()匹配是很重要的。

这个错误很容易发生在返回大量数据的API调用上,即使返回的数据小于1 MB(如果其他事务仍在运行)。

例如,PackageManager.getInstalledApplication()调用返回已安装的所有应用程序的列表。添加特定的标志可以检索大量额外的数据。这样做很可能会失败,所以建议不要检索任何额外的数据,并在每个应用程序的基础上检索这些数据。

然而,调用仍然可能失败,因此重要的是用一个捕获来包围它,并在必要时能够重试。

据我所知,除了重新尝试并确保检索尽可能少的信息之外,没有解决这个问题的方法。

其他回答

有时活动包括一些片段时,活动需要完全重新创建片段内容, 如果sportFragmentManager.fragments没有清晰的历史片段

    val fragments = sportFragmentManager.fragments
    val transaction = sportFragmentManager.beginTransaction()
    for (frag in fragments){
        transaction.remove(frag)
    }
    transaction.commitAllowingStateLoss()

几次重新创建片段活动将发生(调试使用tooLargeTool)

 W/ActivityStopInfo: Bundle stats:
 W/ActivityStopInfo:   android:viewHierarchyState [size=2304]
 W/ActivityStopInfo:     android:views [size=2256]
 W/ActivityStopInfo:   android:support:fragments [size=519072]
 W/ActivityStopInfo: PersistableBundle stats:
 W/ActivityStopInfo:   [null]

当我试图通过Intent发送位图时,我也遇到了同样的问题,同时当它发生时,我折叠了应用程序。

当Activity处于停止的过程中,这意味着Activity试图将其保存的状态Bundles发送到系统操作系统,以便以后(在配置更改或进程死亡之后)安全恢复,但它发送的一个或多个Bundles太大了。

我通过重写onSaveInstanceState在我的活动中解决了这个问题:

@Override
protected void onSaveInstanceState(Bundle outState) {
    // super.onSaveInstanceState(outState);
}

注释调用super。这是一个肮脏的hack,但它是完美的工作。位图成功发送,没有崩溃。 希望这能帮助到一些人。

我遇到了相同的问题与ViewPager2和FragmentStateAdapter这里的问题是FragmentStateAdapter标记'saveState()'作为最终和ViewPager2类也是最终的,所以我们不能覆盖的方法,建议在其他答案使现有的答案不适用。

在我的情况下,我能够摆脱事务太大的问题,不保存分页器的状态添加\android:saveEnabled="false" '在XML条目的视图分页器

<androidx.viewpager2.widget.ViewPager2
    android:saveEnabled="false"
    android:id="@+id/viewPager"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" />

我们的应用程序也有这个问题。经过测试,发现当应用程序内存不足,活动回收时,系统调用onSaveInstanceState方法保存大量的bundle数据,而且每次数据都变大,最后报错TransactionTooLargeException,所以我认为这个方法应该可以解决这个问题。

public final int MAX_BUNDLE_SIZE = 300;
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
     super.onSaveInstanceState(outState);
     long bundleSize = getBundleSize(outState);
     if (bundleSize > MAX_BUNDLE_SIZE * 1024) {
         outState.clear();
     }
}

private long getBundleSize(Bundle bundle) {
     long dataSize;
     Parcel obtain = Parcel.obtain();
     try {
         obtain.writeBundle(bundle);
         dataSize = obtain.dataSize();
     } finally {
        obtain.recycle();
     }
     return dataSize;
}

我也在三星S3上得到了这个例外。 我认为有两个根本原因,

如果你有位图,它会占用太多内存,使用缩小 你在drawable-_dpi文件夹中丢失了一些drawables, android在drawable中寻找它们,并调整它们的大小,使你的setContentView突然跳转并使用大量内存。

使用DDMS并在你播放你的应用程序时查看你的堆,这将给你一些关于哪个setcontentview正在创建问题的指示。

我复制了所有文件夹中的所有图纸,以摆脱问题2。

问题解决了。