3

我正在像这样更新小部件中的一个位图(整个小部件只有一个 ImageView)

remoteViews.setImageViewBitmap(...)

在一些罕见的情况下(在每天使用的 6 个月中发生 3 次)我得到“!!! BINDER TRANSACTION 失败!!!”。那么,只有手机重启才能解决这个问题。再次卸载并安装,没有帮助,只能重新启动。

我检查了图标的大小,它只有 56 KB,所以它符合 IPC 内存限制。当我删除 setImageViewBitmap(...) 小部件再次工作,但位图没有更新。所以问题出在位图本身。当bitmal这么小时,什么可能导致这个活页夹交易失败?

现在,我通过将图标保存到 /data 来解决这个问题,并且我只将 URI 发送到小部件。但我想知道,当我显然没有达到 IPC 内存限制时,哪里会出现问题?

编辑:我忘了提,它发生在 android 2.3.5 和 2.3.7

4

3 回答 3

4

似乎我们无法解析超过 1 mb 的意图。

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

Binder 事务缓冲区有一个有限的固定大小,目前为 1Mb,由进程正在进行的所有事务共享。因此,当有许多事务正在进行时,即使大多数单个事务的大小适中,也可能会引发此异常。

当远程过程调用引发 TransactionTooLargeException 时,有两种可能的结果。客户端无法将其请求发送到服务(很可能是因为参数太大而无法放入事务缓冲区),或者服务无法将其响应发送回客户端(很可能如果返回值是太大而无法放入事务缓冲区)。无法判断这些结果中的哪些实际发生了。客户端应该假设发生了部分故障。

避免 TransactionTooLargeException 的关键是保持所有事务相对较小。尽量减少为参数和远程过程调用的返回值创建 Parcel 所需的内存量。避免传输大量字符串或大型位图。如果可能的话,试着把大的请求分解成更小的部分。

如果您正在实现一项服务,那么对客户端可以执行的查询施加大小或复杂性约束可能会有所帮助。例如,如果结果集可能会变大,则不允许客户端一次请求多于几条记录。或者,不要一次返回所有可用数据,而是先返回基本信息,然后让客户根据需要稍后要求提供其他信息。

于 2012-04-23T13:31:59.843 回答
2

这是因为对 RemoteViews 的所有更改都是序列化的(例如 setInt 和 setImageViewBitmap )。位图也被序列化成一个内部包。不幸的是,这个捆绑包的大小限制非常小。

您可以通过以下方式缩小图像大小来解决它:

public static Bitmap scaleDownBitmap(Bitmap photo, int newHeight, Context context) {

final float densityMultiplier = context.getResources().getDisplayMetrics().density;        

int h= (int) (newHeight*densityMultiplier);
int w= (int) (h * photo.getWidth()/((double) photo.getHeight()));

photo=Bitmap.createScaledBitmap(photo, w, h, true);

return photo;
}

选择 newHeight 足够小(屏幕上的每个正方形约为 100)并将其用于您的小部件,您的问题将得到解决:)

于 2011-12-31T14:23:24.243 回答
1

如果您正在重用您的 remoteViews 变量:每次更新同一位图时ImageView,这都会记录为单独的远程视图操作。无法清除或删除与 关联的操作列表RemoteViews。在这种情况下你唯一能做的就是重新创建 remoteVies 而不是无限地重用它

于 2015-10-16T12:25:41.383 回答