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


当前回答

这一行代码在writeToParcel(包裹dest, int标志)方法帮助我摆脱TransactionTooLargeException。

dest=Parcel.obtain(); 

在这段代码之后,我只写所有的数据到包裹对象,即dest.writeInt()等。

其他回答

这一行代码在writeToParcel(包裹dest, int标志)方法帮助我摆脱TransactionTooLargeException。

dest=Parcel.obtain(); 

在这段代码之后,我只写所有的数据到包裹对象,即dest.writeInt()等。

对我来说,它也是FragmentStatePagerAdapter,然而覆盖saveState()不起作用。以下是我的解决方法:

当调用FragmentStatePagerAdapter构造函数时,在类中保持一个单独的片段列表,并添加一个方法来删除这些片段:

class PagerAdapter extends FragmentStatePagerAdapter {
    ArrayList<Fragment> items;

    PagerAdapter(ArrayList<Fragment> frags) {
        super(getFragmentManager()); //or getChildFragmentManager() or getSupportFragmentManager()
        this.items = new ArrayList<>();
        this.items.addAll(frags);
    }

    public void removeFragments() {
        Iterator<Fragment> iter = items.iterator();

        while (iter.hasNext()) {
            Fragment item = iter.next();
                getFragmentManager().beginTransaction().remove(item).commit();
                iter.remove();
            }
            notifyDataSetChanged();
        }
    }
    //...getItem() and etc methods...
}

然后在Activity中,保存ViewPager的位置,并在重写的onSaveInstanceState()方法中调用adapter.removeFragments():

private int pagerPosition;

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    //save other view state here
    pagerPosition = mViewPager.getCurrentItem();
    adapter.removeFragments();
}

最后,在重写的onResume()方法中,如果适配器不为空,则重新实例化它。(如果它是空的,那么Activity是第一次被打开或应用程序被Android杀死后,onCreate将做适配器创建。)

@Override
public void onResume() {
    super.onResume();
    if (adapter != null) {
        adapter = new PagerAdapter(frags);
        mViewPager.setAdapter(adapter);
        mViewPager.setCurrentItem(currentTabPosition);
    }
}

我们的应用程序也有这个问题。经过测试,发现当应用程序内存不足,活动回收时,系统调用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;
}

我遇到过这个问题,我发现当服务和应用程序之间交换大量数据时(这涉及传输大量的缩略图)。实际上数据大小在500kb左右,IPC事务缓冲区大小设置为1024KB。我不确定为什么它超过了事务缓冲区。

当您通过intent extras传递大量数据时,也会发生这种情况

当您在应用程序中遇到此异常时,请分析您的代码。

您是否在服务和应用程序之间交换了大量数据? 使用intent共享海量数据,(例如用户从gallery共享中选择大量文件按share,所选文件的uri将使用intent传输) 从服务接收位图文件 等待android返回大量数据(例如,当用户安装了大量应用程序时,getInstalledApplications()) 使用applyBatch()处理大量未决操作

当你得到这个异常时如何处理

如果可能的话,将大操作拆分为小块,例如,调用applyBatch()时不要使用1000个操作,而是每个操作使用100个。

服务和应用之间不交换大数据(>1MB)

我不知道怎么做,但是,不要查询android,它可以返回巨大的数据:-)

有这么多地方TransactionTooLargeException可以发生——这里是Android 8的一个新情况——当有人开始输入EditText时,如果内容太大,就会崩溃。

它与AutoFillManager (API 26中新增)和StartSessionLocked()中的以下代码相关:

    mSessionId = mService.startSession(mContext.getActivityToken(),
            mServiceClient.asBinder(), id, bounds, value, mContext.getUserId(),
            mCallback != null, flags, mContext.getOpPackageName());

如果我理解正确的话,这调用了自动填充服务——在绑定器中传递AutofillManagerClient。当EditText有很多内容时,它似乎会引起TTLE。

在EditText的xml布局声明中添加android:importantForAutofill="noExcludeDescendants"。或者在代码中:

EditText et = myView.findViewById(R.id.scriptEditTextView);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    et.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS);
}

第二种糟糕的解决方法可能是重写performClick()和onWindowFocusChanged()方法来捕获TextEdit子类本身的错误。但我不认为这是明智的……