【问题标题】:Android GroundoverLay consumes lot of memoryAndroid GroundoverLay 消耗大量内存
【发布时间】:2018-03-24 23:32:25
【问题描述】:

我正在开发 Android Weather 应用程序,我的要求是显示动画预报。我们有一个服务器,我使用 Glide 将预测图像加载为位图,然后使用位图创建 GoogleMap 的 GroundOveryayOption。 我正在使用 Runnable 和 Handler 制作动画。

除了内存消耗外,一切正常,最终我得到“内存不足异常”

为了顺利运行我的预测动画,我必须使用 Glide 加载所有位图并从位图创建 GroundOverlayOptions obj 并将 GroundOverlayOptions 存储在 HashMap 中,如下所示。

    @Override
            public void onResourceReady(@NonNull Bitmap bitmap, @Nullable Transition<? super Bitmap> transition) {
                mBitmapLoaded = true;

//the actual image is png and its size is in KBs but Bitmap size is in MBs
                Log.i("Weather", ""+ bitmap.getByteCount());

                GroundOverlayOptions overlayOptions = new GroundOverlayOptions()
                        .image(BitmapDescriptorFactory.fromBitmap(bitmap))
                        .positionFromBounds(getLatLngBounds(mBounds))
                        .visible(frameVisible);

    //groundOverlaysItemMap is a Hashmap to store GroundOverlayOptions where key is Time
                groundOverlaysItemMap.put(mTime, mMap.addGroundOverlay(overlayOptions));
            }

感谢任何帮助。

【问题讨论】:

  • 您可能只想将 .png 文件保存在内存中,并且仅在需要时才绘制它们,以便在任何时候都只有其中一个处于解压缩形式。更多 CPU 使用率,更多更少 RAM 使用率。
  • 我需要提前创建 GroundOverlayOption 对象,以免影响动画如下 GroundOverlayOptions overlayOptions = new GroundOverlayOptions() .image(BitmapDescriptorFactory.fromBitmap(bitmap)) .positionFromBounds(getLatLngBounds(mBounds)) 。可见(frameVisible);
  • 将图像下采样到可以容忍的最低分辨率。

标签: android google-maps


【解决方案1】:

将您的“大”图像分割成“小”(例如256x256 像素)图块(例如MapTiler 就像在this 视频中一样),将它们保存到raw 文件夹(或设备存储)并使用TileProvider 喜欢that Alex Vasilkov 的回答:

public class CustomMapTileProvider implements TileProvider {
    private static final int TILE_WIDTH = 256;
    private static final int TILE_HEIGHT = 256;
    private static final int BUFFER_SIZE = 16 * 1024;

    private AssetManager mAssets;

    public CustomMapTileProvider(AssetManager assets) {
        mAssets = assets;
    }

    @Override
    public Tile getTile(int x, int y, int zoom) {
        byte[] image = readTileImage(x, y, zoom);
        return image == null ? null : new Tile(TILE_WIDTH, TILE_HEIGHT, image);
    }

    private byte[] readTileImage(int x, int y, int zoom) {
        InputStream in = null;
        ByteArrayOutputStream buffer = null;

        try {
            in = mAssets.open(getTileFilename(x, y, zoom));
            buffer = new ByteArrayOutputStream();

            int nRead;
            byte[] data = new byte[BUFFER_SIZE];

            while ((nRead = in.read(data, 0, BUFFER_SIZE)) != -1) {
                buffer.write(data, 0, nRead);
            }
            buffer.flush();

            return buffer.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } catch (OutOfMemoryError e) {
            e.printStackTrace();
            return null;
        } finally {
            if (in != null) try { in.close(); } catch (Exception ignored) {}
            if (buffer != null) try { buffer.close(); } catch (Exception ignored) {}
        }
    }

    private String getTileFilename(int x, int y, int zoom) {
        return "map/" + zoom + '/' + x + '/' + y + ".png";
    }
}

【讨论】:

  • 我的要求是使用 GroundOverlay 而不是 TileOverlay。
  • 有 2 种可能减少内存消耗:1)将大图像分割成小块(瓦片)2)下采样图像。 TileOverlay 几乎是 GroundOverlay,但为了获得最佳性能并避免消耗大量内存,将其拆分为多个部分。另一种方法是将图像下采样到最低分辨率,如建议的JimmyB。此外,您可以使用android:largeHeap="true" 请求更大的堆大小,但这不是一个好的解决方案。
猜你喜欢
  • 2022-01-16
  • 2014-01-04
  • 2012-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多