【问题标题】:Can a handler with big msg.obj throw TransactionTooLargeException?带有大 msg.obj 的处理程序可以抛出 TransactionTooLargeException 吗?
【发布时间】:2023-03-25 23:16:01
【问题描述】:

我注意到 Google Console 中报告了很多异常:

java.lang.RuntimeException: 
  at android.app.servertransaction.PendingTransactionActions$StopInfo.run (PendingTransactionActions.java:160)
  at android.os.Handler.handleCallback (Handler.java:873)
  at android.os.Handler.dispatchMessage (Handler.java:99)
  at android.os.Looper.loop (Looper.java:201)
  at android.app.ActivityThread.main (ActivityThread.java:6815)
  at java.lang.reflect.Method.invoke (Method.java)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:547)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:873)
Caused by: android.os.TransactionTooLargeException: 
  at android.os.BinderProxy.transactNative (BinderProxy.java)
  at android.os.BinderProxy.transact (BinderProxy.java:1131)
  at android.app.IActivityManager$Stub$Proxy.activityStopped (IActivityManager.java:3973)
  at android.app.servertransaction.PendingTransactionActions$StopInfo.run (PendingTransactionActions.java:144)
  at android.os.Handler.handleCallback (Handler.java:873)
  at android.os.Handler.dispatchMessage (Handler.java:99)
  at android.os.Looper.loop (Looper.java:201)
  at android.app.ActivityThread.main (ActivityThread.java:6815)
  at java.lang.reflect.Method.invoke (Method.java)
  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:547)
  at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:873)

我试图弄清楚是什么引发了该异常,但我做不到。我的源代码中唯一可疑的部分是我正在加载一个非常大的 json 文件(7MB),使用 GSON 将其解析为模型(data 对象),并将其通过处理程序传递给我的活动:

Message msg = new Message();
msg.what = Util.THREAD_DATA_GENERATED;
msg.obj = data;
handler.sendMessage(msg);

。 . .

notifyHandler = new Handler(new Handler.Callback() {
    @Override
    public boolean handleMessage(Message msg) {
        Data data = (Data) msg.obj;
        Manager.getInstance().setData(data);
        showSelectTeamDialog();
        return true;
    }
});

当传递一个大尺寸的 msg.obj 参数时,这个处理程序会抛出那个异常吗?

【问题讨论】:

    标签: android handler android-handler transactiontoolargeexception


    【解决方案1】:

    处理程序不会。但是可以通过 Intent 将该数据发送到 Activity。数据被序列化以用于可能的跨进程消息传递,并且存在数据大小限制(曾经是 2MB,不确定是否已更改)。我敢打赌 showSelectTeamDialog 正在启动一个 Activity 来显示对话框,这就是失败的原因。

    查看堆栈跟踪。它包括:

    在 android.app.IActivityManager$Stub$Proxy.activityStopped (IActivityManager.java:3973)

    所以活动由于某种原因停止了。发生这种情况的唯一原因是调用了完成,或者启动了另一个活动。所以我们肯定在这里的 Intent 中看到了太多的数据。

    【讨论】:

    • 我正在使用 putSerializable 将一小部分数据放入对话框中,但该部分只是模型总大小的 1/9。这会导致应用程序崩溃吗?
    • 可能吗?我可能错了,允许的尺寸可能更小。 Intent 由 Bundle 支持,但我认为在意图实际发送到某处之前不会检查大小。导致异常的是发送,而不是添加数据。这就是为什么 putSerializable 不在堆栈跟踪中的原因。在活动/服务尝试启动之前不会检测到错误。
    • 多么疯狂的事情,我需要创建一个单例来在活动之间共享数据而不会崩溃。我记得使用 C 的时候,您能够传递对象的引用而不是完整的对象。这是android和java的一大败笔。
    • 我记得现代 Android 操作系统级别的事务大小限制为 512KB。此外,这些交易被更多的客户使用,而不仅仅是你,所以你真的应该尽量保持你放入它们的东西非常小。听起来您可能想将 json 写入磁盘,然后发送文件路径而不是实际数据(然后从另一端的磁盘加载数据)。
    • 文档 (developer.android.com/reference/android/os/…) 说当前的限制是 1MB,但出于某种原因,我强烈认为我读过它实际上比这更小。也许我读到的只是建议仅使用 50% 的利用率,以便在共享事务中为其他客户端留出空间。
    猜你喜欢
    • 1970-01-01
    • 2012-04-01
    • 2010-09-12
    • 2014-10-20
    • 2021-11-05
    • 2019-04-24
    • 2021-05-17
    • 2011-05-25
    • 1970-01-01
    相关资源
    最近更新 更多