Android Loading标记动态最佳策略

Dav*_*vid 9 android google-maps dynamic

我有一个谷歌地图的Android地图,可以根据用户的屏幕位置从服务器动态加载标记.因此,例如,如果用户移动地图,我只是向服务器发出请求,并且我正在发送屏幕边界,并且基于此我得到标记数据(id和corrdinates),稍后将其解析并创建为实际指针.问题是,当用户返回到同一区域(之前创建了哪些标记)时,我仍然提出相同的请求并获得相同的数据(但显然我不会让重新创建该标记,所以我只是在那里运行所有标记的循环在地图上并检查地图标记id是否相等服务器发送数据标记ID,如果它相等,我只是打破循环)

try {
                Collection<MarkerItemData> mapMarkers = algorithm.getItems();
                JSONObject jsonObject = new JSONObject(strings[0]);
                JSONArray respondArray = jsonObject.getJSONArray("respond");
                list = new ArrayList();
                for (int i = 0; i < respondArray.length(); i++) {
                    JSONObject station = respondArray.getJSONObject(i);
                    int id = station.getInt("_id");
                    boolean skip = false;
                    for (final MarkerItemData m : mapMarkers) {
                        if (m.getId() == id) {
                            skip = true;
                            break;
                        }
                    }
                }
            }
Run Code Online (Sandbox Code Playgroud)

但是我不认为这种方法是最好的.我还有其他想法应该有效(至少我认为)

  • 发送到服务器屏幕边界以及屏幕上可见的所有标记ID(我可以选择屏幕范围内的所有标记以及哪些ID不在屏幕范围内)
  • 每次从Android应用程序中删除标记,基本上每次都从服务器重新创建所有标记(我个人认为这是一个糟糕的解决方案)

那么哪些想法最好?还有其他想法吗?(对不起我的英语不好)

Dor*_*lan 2

将屏幕边界发送到服务器和屏幕上当前可见标记的 id-s 是您最好的选择。但仍然存在一些麻烦的问题。如何找到屏幕边界指定范围内包含的所有标记?如果新标记到达您的服务器或某些标记被删除怎么办?在这种情况下,你能提供一个可维护的结构吗?还是你会一一测试数据库中与标记相对应的每个点,看看它是否位于范围内?考虑到所有这些,您需要找到一种方法来优化存储和查询点,即点标记的纬度和经度对。您应该使用一种常见的空间索引方法来执行空间索引。

空间索引的方法有很多,根据用例,一种方法可能比另一种方法稍好。长话短说,由于您需要在这种情况下查询范围,因此您应该实现四叉树。四叉树被称为树形数据结构,其中每个内部节点恰好有四个子节点(西北、东北、西南、东南)。如果你对这个结构没有了解,我相信你一个小时就能明白它的基础知识,但从头开始详细解释会导致我损失太多时间。因此,我跳过有关四叉树的实现细节。有几个来源已经比我更好地解释了这种结构,并且您可以轻松找到开源库。

我只会为你的四叉树提供伪 Java 方法来查找屏幕边界范围内出现的所有点,不包括上一个屏幕中已经存在的点:

ArrayList<LatLng> queryRange(QuadLevel level, float[] screenBounds, ArrayList<LatLng> prevPoints) { 

    // Initialize a list to hold the found points
    ArrayList<LatLng> pointsInRange = new ArrayList<>();

    if (!quadtreeBounds.intersects(screenBounds))
        return pointsInRange;

    // Find the points that are in the current quad level
    for (LatLng point : level.getPoints()) {
        // If the current point is in screen bounds and it is not contained by prevPoints
        if (point.isInRange(screenBounds) 
            && !prevPoints.contains(point))
            pointsInRange.add(point);
    }

    // If there are no children, return
    if (level.hasNoChildren())
        return pointsInRange;

    // Else, continue to look up children
    pointsInRange.addAll(queryRange(level.northwest, screenBounds, prevPoints));
    pointsInRange.addAll(queryRange(level.northeast, screenBounds, prevPoints));
    pointsInRange.addAll(queryRange(level.southwest, screenBounds, prevPoints));
    pointsInRange.addAll(queryRange(level.southeast, screenBounds, prevPoints));

    return pointsInRange;
}
Run Code Online (Sandbox Code Playgroud)