我得到了一个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


当前回答

如果你使用导航组件的ViewPager2 FragmentStateAdapter:

我在onViewCreated()中创建适配器,但每次导航回来时都会重新创建视图。由于某种原因,旧的适配器没有正确地分离并增加包的大小,直到错误发生。 我用TooLargeTool调试它,解决方案是避免在onViewCreated()中重新创建适配器。

在我的片段中,我有适配器变量:

var pagerAdapter:HomePagerAdapter?=null

在onViewCreated方法中,我只创建了一次适配器:

if(pagerAdapter == null){
  pagerAdapter = HomePagerAdapter(childFragmentManager, lifecycle, myContent)
}

为了防止IllegalArgumentException,我手动从onDestroyView中的分页器中分离适配器:

override fun onDestroyView() {
   pager.adapter = null
   super.onDestroyView()
}

其他回答

TransactionTooLargeException已经困扰我们大约4个月了,我们终于解决了这个问题!

发生的是我们在ViewPager中使用FragmentStatePagerAdapter。用户将翻页并创建100多个片段(这是一个阅读应用程序)。

虽然我们在destroyItem()中正确地管理片段,但在android中 FragmentStatePagerAdapter的实现有一个bug,它保持了对以下列表的引用:

private ArrayList<Fragment.SavedState> mSavedState = new ArrayList<Fragment.SavedState>();

当Android的FragmentStatePagerAdapter尝试保存状态时,它将调用该函数

@Override
public Parcelable saveState() {
    Bundle state = null;
    if (mSavedState.size() > 0) {
        state = new Bundle();
        Fragment.SavedState[] fss = new Fragment.SavedState[mSavedState.size()];
        mSavedState.toArray(fss);
        state.putParcelableArray("states", fss);
    }
    for (int i=0; i<mFragments.size(); i++) {
        Fragment f = mFragments.get(i);
        if (f != null && f.isAdded()) {
            if (state == null) {
                state = new Bundle();
            }
            String key = "f" + i;
            mFragmentManager.putFragment(state, key, f);
        }
    }
    return state;
}

正如您所看到的,即使您正确地管理FragmentStatePagerAdapter子类中的片段,基类仍然会存储一个片段。SavedState用于创建的每个片段。TransactionTooLargeException会在数组被转储到parcelableArray时发生,而操作系统不希望它有100+项。

因此,我们的解决方案是重写saveState()方法,不为“状态”存储任何东西。

@Override
public Parcelable saveState() {
    Bundle bundle = (Bundle) super.saveState();
    bundle.putParcelableArray("states", null); // Never maintain any states from the base class, just null it out
    return bundle;
}

确保你没有在Intent对象中放入大容量的数据。在我的情况下,我添加字符串500k大小,然后开始另一个活动。除了这个例外,它总是失败。我通过使用活动的静态变量避免了在活动之间共享数据——你不需要将它们发送到Intent,然后从Intent中提取。

我有的:

String html = new String();//some string of 500K data.
Intent intent = new Intent(MainActivity.this, PageWebView.class);
//this is workaround - I just set static variable and then access it from another    activity.
MainActivity.htmlBody = timelineDb.getHTMLBodyForTweet(tweet);
//This line was present and it actually failed with the same exception you had.
//intent.putExtra("com.gladimdim.offtie.webview", html);

我遇到了相同的问题与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" />

有时活动包括一些片段时,活动需要完全重新创建片段内容, 如果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]

在我的情况下,TransactionTooLargeException的原因是我在参数中发送大数据片段(使用Bundle),像这样:

        var arguments = Bundle()
        arguments.putSerializable("argumentName", argumentValue)
        fragment.arguments = arguments

只有当argumentValue的大小较小(例如Int或String)时,它才能正常工作, 但如果它有很大的大小(例如DTO列表)-你可以得到TransactionTooLargeException。 现在我在构造函数中传递参数给fragment,一切正常。

PS 感谢sulai提供TooLargeTool