gpt4 book ai didi

java - 将大型 GeoJson 添加到 Android 上的 GoogleMap 的有效方法

转载 作者:行者123 更新时间:2023-12-04 03:50:54 24 4
gpt4 key购买 nike

我有一个 3 公里网格的某个区域的温度图。IE。我有大约几千个带颜色的多边形。

我正尝试在我的 kotlin 应用程序中将它们显示在 Android 版 Google map 上。

问题是我需要在 UI 线程中添加 GeoJson 层,这需要 8-15 秒。 IE。一直以来,应用程序都被卡住了

StackOverflow 上有很多关于这个问题的旧答案,但它们都与我无关:

  1. 他们建议减少 json - 我已经从具有相同值的附近方 block 创建了集群
  2. 他们建议使用 MapView 和叠加层 - 但在最新的谷歌地图 API 中,没有 MapView 和在后台线程中添加叠加层的能力

我试过:

  1. map.addPolygon 而不是创建 GeoJsonLayer
  2. 使用 GroundOverlay 映射 addOverlay

当 UI 被卡住时,我仍然有或多或少相同的时间

我该如何处理这个问题?有什么方法可以在后台线程中从数千个彩色矩形创建 map ,然后立即在 UI 线程中显示它?

最佳答案

如果您已经尝试过 addPolygon()GroundOverlay,则还有两种可能性:

  1. 使用 Tile Overlays (首选);

  2. MapView 上使用自定义绘图或 MapFragment .

IMHO Tile Overlay 是一种更好的方式,因为它可能具有高性能 TileProvider执行。例如,您可以为“低”缩放级别和“当前”(应在开始时向用户显示的级别)缩放级别创建图 block 并将它们存储在数组(HashMap 等)中或文件系统路径 ..\zoom_level\x\y\tile.png 如果有很多图 block 。还有更多“详细”图 block ,您可以在需要显示时“即时”创建(在单独的线程中),然后存储它们以备将来使用(如果需要)。当然,您需要自定义模块来快速读取 GeoJson(类似于 Jackson)并将其呈现为 .png 磁贴。因此,似乎可以为您的情况创建 TileProvider,通过性能和内存消耗进行优化。您可以使用 this answerAlex Vasilkov作为第一次迭代。

如果您选择自定义绘图,您应该覆盖 MapViewonDraw() 方法或 MapFragmentdispatchDraw() >。就像在this answer .在那种情况下,您可以控制所有过程,但这种方式实现起来更加复杂。

更新:

您可以为 onCameraMove() 执行操作,如 this答案(那里使用的 GoogleMap 对象的一些棘手传递):

public class RadarMapView extends MapView implements OnMapReadyCallback {

private OnMapReadyCallback mMapReadyCallback;
private GoogleMap mGoogleMap;
private Marker mMarker;
private Paint mPaintRadar;

public RadarMapView(@NonNull Context context) {
super(context);
init();
}

public RadarMapView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}

public RadarMapView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}

public RadarMapView(@NonNull Context context, @Nullable GoogleMapOptions options) {
super(context, options);
init();
}

@Override
public void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
canvas.save();
drawRadarOverTheMap(canvas);
canvas.restore();
}

private void drawRadarOverTheMap(Canvas canvas) {
if (mGoogleMap == null) {
return;
}

final float centerX = getX() + getWidth() / 2;
final float centerY = getY() + getHeight() / 2;

canvas.drawCircle(centerX, centerY, 150, mPaintRadar);
canvas.drawCircle(centerX, centerY, 300, mPaintRadar);
canvas.drawCircle(centerX, centerY, 450, mPaintRadar);
}

private void init() {
setWillNotDraw(false);

mPaintRadar = new Paint();
mPaintRadar.setColor(Color.GREEN);
mPaintRadar.setStyle(Paint.Style.STROKE);
mPaintRadar.setStrokeWidth(10);
}

@Override
public void getMapAsync(OnMapReadyCallback callback) {
mMapReadyCallback = callback;
super.getMapAsync(this);
}

@Override
public void onMapReady(GoogleMap googleMap) {
mGoogleMap = googleMap;
mGoogleMap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() {
@Override
public void onCameraMove() {
invalidate(); // NB! Exactly this line you need
}
});
if (mMapReadyCallback != null) {
mMapReadyCallback.onMapReady(googleMap);
}
}

}

更新#2:

您可以制作多边形当前 View 的“屏幕截图”(不完全是屏幕截图,而是在位图上创建多边形图像)并在 onCameraMove() 中移动它(不是重绘所有多边形)。然后在 onCameraIdle() 中创建并显示新的全多边形 View 。此外,您可以创建比 map 屏幕 View 稍大的位图(用于缩小和正确滚动)。或者您可以“跳过”一些 onCameraMove() 调用(例如,每 3 个 onCameraMove() 调用调用一次 invalidate() 等) .

顺便说一句:如果是 Tile Overlays,移动和缩放是“开箱即用”的。您只需要创建一个棘手的 TileProvider。整个设备屏幕只需要生成几个图 block (单个图 block 的大小为 256x256)。因此,您可以为当前屏幕、currentZoomLevel-1、currentZoomLevel+1(在缩放的情况下)和向左、右、顶部和底部生成 + 2(或 3)个图 block (在滚动的情况下)。您还可以存储生成的图 block 以供将来在某些缓存(HashMap、LRU 等)中使用。并且您可以在单独的线程中生成“额外的”(当前不可见的)图 block 。

关于java - 将大型 GeoJson 添加到 Android 上的 GoogleMap 的有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64416577/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com