Android 异常:失败的 BINDER TRANSACTION

Posted

技术标签:

【中文标题】Android 异常:失败的 BINDER TRANSACTION【英文标题】:Android exception : FAILED BINDER TRANSACTION 【发布时间】:2016-03-23 16:27:51 【问题描述】:

我有一个Service,它在我的应用程序启动时在后台运行,并在应用程序关闭后继续运行。从Content Provider 注册的UriimplementsLoader.OnLoadCompleteListener<Cursor>。当在回调方法onLoadComplete(Loader<Cursor> loader, Cursor data) 上传递新的Cursor 对象时,我然后使用Cursor 运行AsyncTask 以创建实现Parcelable interface 的自定义ObjectsArrayList。一旦处理完毕,如果应用程序打开,它将使用 IPC 框架发送回应用程序,使用HandlerMessengerMessages 和 aBundle 进行编组/解组。如果应用程序未打开,则 ArrayList 准备好在打开后发送回应用程序,应用程序在打开时调用Service

问题:

ArrayList 可以变得相对较大(它不包含Bitmaps,仅包含Primitives 和几个短的String 对象)并且绝对数量意味着当ArrayList 获取时它会达到FAILED BINDER TRANSACTION大约 700 个对象。

当前解决方案(感觉有点老套)

我将ArrayList 拆分为多个块,并将几个Messages 发送回Handler,然后将其重构为一个ArrayList,然后在应用程序中使用(更新RecyclerViews 等)。

我使用这种方法是因为性能显着提高 - 只需要在第一次启动 App/Service 时进行初始查询,而不是每次打开 App 时总是查询Content Provider

我之所以说“hacky”是因为这感觉像是针对Binder Framework 限制的一种解决方法,而不是一种解决方案。

欢迎任何有关以不同方式处理此问题的建议。

【问题讨论】:

【参考方案1】:

我想到的两个选择是:

    在您的服务中拥有一个静态 ArrayList,并在收到光标时向 Activity 发送广播,以将服务内部的静态 Arraylist 的内容复制到 Activity 内的本地 ArrayList 中。通过这种方式,Activity 仅在复制内容时才引用静态 aarraylist。

    我会将内容异步保存在 sql 数据库中,然后向活动发送广播以再次异步检索数据库中的游标。在 UI 线程上,我会在适配器上调用 notifydatasetChanged。

【讨论】:

感谢您的回复,这两个想法都非常合理。我确实考虑过使用静态 ArrayList,但由于范围的原因,尽量避免使用静态变量,在这种情况下,访问其他线程可以尝试同时访问和修改的全局变量。我可能会使用 Sql 数据库,或者使用完全不同的方法重新开始。 我也会采用第二种方法,我同意您的意见。如果我们能得到另一个我也感兴趣的答案会很有趣。 我决定采用不同的方法 - 我将使用自定义 AsyncTaskLoader - 如果正确实施,这应该提供我所追求的稳定性。在这种情况下使用数据库感觉就像加倍处理 - 查询内容提供者,然后将数据插入我自己的数据库感觉就像加倍处理,因为我只需要再次查询数据库并创建自定义 POJO无论如何,对象都会形成它。

以上是关于Android 异常:失败的 BINDER TRANSACTION的主要内容,如果未能解决你的问题,请参考以下文章

android中的Binder运行时异常

Android - 包裹自定义类型 - BINDER TRANSACTION 失败

系统稳定性 - 调优3.4 常见Binder相关异常调优总结

Android Binder 的主要内容概述以及特性和原理

Android中的Binder机制的简要理解

Android笔记 - Binder之请求注册Service组件