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


当前回答

尝试使用EventBus或ContentProvider之类的解决方案。

如果你在同一个进程中(通常你所有的活动都是),尽量使用EventBus,因为在进程中数据交换不需要一个缓冲,所以你不需要担心你的数据太大。(你可以只使用方法调用来传递数据,而EventBus隐藏了丑陋的东西) 细节如下:

// one side
startActivity(intentNotTooLarge);
EventBus.getDefault().post(new FooEvent(theHugeData));

// the other side
@Subscribe public void handleData(FooEvent event) { /* get and handle data */ }

如果Intent的双方不在同一个进程中,可以尝试一些ContentProvider。


看到TransactionTooLargeException

Binder事务失败,因为它太大了。 在远程过程调用期间,调用的参数和返回值作为Parcel对象传输,存储在Binder事务缓冲区中。如果参数或返回值太大,无法放入事务缓冲区,则调用将失败,并抛出TransactionTooLargeException。

其他回答

我也面临着这个问题的位图数据从一个活动传递到另一个,但我通过使我的数据作为静态数据的解决方案,这对我来说是完美的工作

在活动中首先:

public static Bitmap bitmap_image;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_first);
   bitmap_image=mybitmap;
}

在第二个活动中:

 @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_second);
   Bitmap mybitmap=first.bitmap_image;
}

有这么多地方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子类本身的错误。但我不认为这是明智的……

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

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

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

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

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

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

我最近也遇到了这个问题,在阅读了这个和其他网站上的所有解决方案2天后,我想分享我的问题的原因和我是如何解决的,因为我没有看到我的问题。

我使用的片段是:

FragmentA ->包含一个位图回收视图 FragmentB ->启动相机并将图像捕获返回到Fragment A

FragmentB有相机的东西,所以我发送位图FragmentA使用previousBackStackEntry像这样:

findNavController().run {
    previousBackStackEntry?.savedStateHandle?.set(KEY_REPORT_PHOTO, photo)
    popBackStack()
}

最后,我在FragmentA上使用位图:

findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<Bitmap>(KEY_REPORT_PHOTO)
    ?.observe(viewLifecycleOwner) {
        it?.let { photo ->
            viewModel.addPhoto(photo)
            findNavController().currentBackStackEntry?.savedStateHandle?.set(KEY_REPORT_PHOTO, null)
        }
    }

阅读本页上的信息,我的第一种方法是找出onSaveInstanceState中发生了什么,并尝试删除回收器视图中的位图,我认为当我关闭应用程序并将其放在后台时正在保存。

最后,我意识到问题是我在导航组件的BackStackEntry中添加的位图,解决方案就像在FragmentA中使用这一行的位图一样简单:

findNavController().currentBackStackEntry?.savedStateHandle?.set(KEY_REPORT_PHOTO, null)

你已经从onSaveInstanceState方法中清除了旧的InstanceState,它会工作得很好。我使用FragmentStatePagerAdapter为我的viewpager,所以我保持下面覆盖方法到我的父活动为清晰的InstanceState。

@Override
protected void onSaveInstanceState(Bundle InstanceState) {
             super.onSaveInstanceState(InstanceState);
             InstanceState.clear();
}

我发现这个解决方案从这里android.os.TransactionTooLargeException在牛轧糖