Android RemoteViews:setImageViewResource()vs setImageViewUri()vs setImageViewBitmap()

时间:2013-09-17 04:32:16

标签: android image memory bitmap android-widget

以下3种方法(来自RemoteViews类)可用于更新Android主屏幕小部件上的图像:

setImageViewResource (int viewId, int srcId)
setImageViewUri (int viewId, Uri uri)
setImageViewBitmap (int viewId, Bitmap bitmap)

但经过大量研究后,我发现setImageViewUri()是最好用的,以避免更新小部件时可能发生的错误"**!!! FAILED BINDER TRANSACTION !!!**"。但为什么会这样呢?我找不到任何正当理由或JavaDoc文档。

2 个答案:

答案 0 :(得分:2)

  

Binder交易失败,因为它太大了。   在远程过程调用期间,调用的参数和返回值将作为存储在Binder事务缓冲区中的Parcel对象传输。如果参数或返回值太大而不适合事务缓冲区,则调用将失败并抛出TransactionTooLargeException。   Binder事务缓冲区具有有限的固定大小,当前为1Mb,由进程正在进行的所有事务共享。因此,即使大多数单个事务的大小适中,当有许多事务正在进行时,也会抛出此异常。   当远程过程调用抛出TransactionTooLargeException时,有两种可能的结果。客户端无法将其请求发送到服务(很可能,如果参数太大而无法放入事务缓冲区中),或者服务无法将其响应发送回客户端(最有可能的话,如果返回值为太大而不适合事务缓冲区)。无法确定实际发生了哪些结果。客户应该假设发生了部分故障。   避免TransactionTooLargeException的关键是保持所有事务相对较小。尝试最小化为参数创建Parcel所需的内存量以及远程过程调用的返回值。避免传输大量字符串或大位图。如果可能的话,尝试将大量请求分解成更小的部分。   如果要实现服务,则可能有助于对客户端可以执行的查询施加大小或复杂性约束。例如,如果结果集可能变大,则不允许客户端一次请求多个记录。或者,不是一次性返回所有可用数据,而是先返回基本信息,然后根据需要让客户要求提供更多信息。

如果你真的想要这样做可能,但它会花费大量内存而且速度也很慢。如果你有一个旧手机和一个大位图,它可能无法正常工作。您可以将其作为额外内容传递,例如intent.putExtra("data", bitmap)。一个Bitmap implements Parcelable,所以你可以把它放在一个额外的地方并用setImageViewBitmap (int viewId, Bitmap bitmap)设置它。

如果你想在活动之间传递它,我会将它存储在一个文件中。这样效率更高,而且工作量更少。您可以使用任何其他应用无法访问的MODE_PRIVATE在您的数据文件夹中创建私人文件。

如果将其作为Parcelable传递,则必然会出现JAVA BINDER FAILURE错误。因此,解决方案是:如果位图很小,比如缩略图,则将其作为字节数组传递,并构建位图以便在下一个活动中显示。例如:

在您的通话活动中......

Intent i = new Intent(this, NextActivity.class);
Bitmap b; // your bitmap
ByteArrayOutputStream bs = new ByteArrayOutputStream();
b.compress(Bitmap.CompressFormat.PNG, 50, bs);
i.putExtra("byteArray", bs.toByteArray());
startActivity(i);

...并在您的接收活动中

if(getIntent().hasExtra("byteArray")) {
    ImageView previewThumbnail = new ImageView(this);
    Bitmap b = BitmapFactory.decodeByteArray(
      getIntent().getByteArrayExtra("byteArray"),0,getIntent().getByteArrayExtra("byteArray").length);        
previewThumbnail.setImageBitmap(b);
}

答案 1 :(得分:1)

有些人建议使用setImageViewUri()来降低冻结主屏幕上小部件的风险。见https://code.google.com/p/android/issues/detail?id=28216#c102