【问题标题】:failed binder transaction on widget update小部件更新失败的活页夹事务
【发布时间】:2011-12-14 21:22:27
【问题描述】:

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

remoteViews.setImageViewBitmap(...)

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

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

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

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

【问题讨论】:

    标签: android android-widget android-appwidget android-binder


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

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

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

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

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

      【讨论】:

      • 粗体没有帮助..它实际上让人很难看。 (我不是反对你的人)
      【解决方案3】:

      这是因为对 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-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多