【问题标题】:Android Wear multiple InputStream decoding to BitmapAndroid Wear 多个 InputStream 解码到 Bitmap
【发布时间】:2017-02-07 13:02:27
【问题描述】:

我从智能手表收到一个 DataMap 对象,其中包含两个 DataMap 对象,一个包含字符串列表(标题、副标题、内容...),另一个包含资产列表

List<DataMap> rootItemDataMap [...]
  DataMap itemFieldsDataMap = rootItem.getDataMap(Constants.ROOT_ITEM_FIELDS);
  DataMap itemImagesDataMap = rootItem.getDataMap(Constants.ROOT_ITEM_IMAGES);

当 onDataChanged 被调用时,我将 itemFieldDataMap 转换为字符串,并将 itemImagesDataMap 转换为资产列表。对于每个资产,我想将资产转换为位图并将其放入位图列表中。但我有一个 OutOfMemoryError:

List<Bitmaps> imagesList = new ArrayList<>();
for (int j = 0; j < itemImagesDataMap.size(); j++) {
        Asset asset = itemImagesDataMap.getAsset(Constants.EXTRA_IMAGE +j);
        Bitmap bitmap = WearableUtils.loadBitmapFromAsset(mGoogleApiClient, asset);
        imagesList.add(bitmap);
}

做得不好的方法是 loadBitmapFromAsset:

public static Bitmap loadBitmapFromAsset(GoogleApiClient mGoogleApiClient, Asset asset) {
    InputStream assetInputStream = Wearable.DataApi.getFdForAsset(mGoogleApiClient, asset).await().getInputStream();
    return BitmapFactory.decodeStream(assetInputStream);
}

我在运行时得到这个异常:

java.lang.OutOfMemoryError: Failed to allocate a 2531852 byte allocation with 1037608 free bytes and 1013KB until OOM
                                                     at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
                                                     at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
                                                     at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:635)
                                                     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:611)
                                                     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:649)
                                                     at com.mangomobi.showtime.contentmanager.WearableUtils.loadBitmapFromAsset(WearableUtils.java:71)
                                                     at com.mangomobi.showtime.contentmanager.ItemFactoryImpl.createItems(ItemFactoryImpl.java:48)
                                                     at com.mangomobi.showtime.contentmanager.WearableContentServiceImpl.onDataChanged(WearableContentServiceImpl.java:136)
                                                     at com.google.android.gms.wearable.WearableListenerService$zzc$1.run(Unknown Source)
                                                     at android.os.Handler.handleCallback(Handler.java:739)
                                                     at android.os.Handler.dispatchMessage(Handler.java:95)
                                                     at com.google.android.gms.wearable.WearableListenerService$zzb.dispatchMessage(Unknown Source)
                                                     at android.os.Looper.loop(Looper.java:148)
                                                     at android.os.HandlerThread.run(HandlerThread.java:61)

我已经尝试过使用 BitmapFactory.Options,但我读到了这个SkImageDecoder::Factory returned null

在我的 WearList 中正确显示图像的唯一方法是获取收到的每个项目的第一张图像,因为 itemImagesDataMap 仅包含一个资产。 如何在 for 循环中加载多个位图而不会在 Android Wear 中出现内存错误,一般来说,在 Android 中?

【问题讨论】:

  • 您是否在将图像发送到手表之前将其缩放到合适的尺寸?
  • 不行,因为我不知道如何根据手表分辨率动态确定图片合适的大小。
  • 要么只是猜测(例如,400px),要么使用数据 API 将尺寸从手表发送到手机。
  • 好的。为什么要使用 DataApi?如何获得尺寸?
  • Data API 是为在两个设备之间传递数据而构建的,因此将屏幕尺寸从手表共享到手机可能是正确的选择。如果您对此更满意,Message API 也可以使用。至于获取大小:DisplayMetrics metrics = getResources().getDisplayMetrics(); displaySize = new Point(metrics.widthPixels, metrics.heightPixels);

标签: java android wear-os android-bitmap android-wear-data-api


【解决方案1】:

您可能需要先查看Loading Large Bitmaps Efficiently,其中提到:

为避免java.lang.OutOfMemory 异常,请在解码之前检查位图的尺寸,除非您绝对相信来源会为您提供大小可预测的图像数据,并且可以轻松放入可用内存中。

您可以尝试根据documentation 中的示例代码所示的目标宽度和高度,使用一种方法来计算样本大小值,该值是2 的幂。正如进一步讨论的那样,

要使用此方法,首先将inJustDecodeBounds 设置为true 进行解码,传递选项,然后使用新的inSampleSize 值和inJustDecodeBounds 设置为false 再次解码。

为了进一步帮助您,您可能需要查看以下相关 SO 帖子中的建议解决方案:

  • 按照SO post 中的建议,通过使用inSampleSize 减少内存消耗来修复OutOfMemory 错误
  • 按照建议here,使用静态方法从外部存储中获取位图。

【讨论】:

  • 我已经尝试使用 BitmapFactory.Option 以及 inJustDecodeBounds 将其设置为 true,然后设置为 false。通过这样做并遵循所有文档提示,我可以避免 OutOfMemoryError 但我收到此消息 ->“SkImageDecoder::Factory 返回 null”并且图像未正确加载磨损。网上关于这条消息的帖子很少,我不明白如何处理
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-05
  • 2015-03-08
  • 1970-01-01
  • 2014-11-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多