2017-03-14 1 views
5

사용자 화면 위치에 따라 서버에서 마커를 동적으로로드하는 Google지도가있는 Android지도가 있습니다. 그래서 예를 들어 사용자가 맵을 움직이면 간단히 서버에 요청을하고 스크린 경계를 보내고 마커 데이터 (id와 corrdinates)를 얻습니다.이 마커 데이터는 나중에 구문 분석되어 실제 포인터로 생성됩니다. 문제는 사용자가 동일한 영역 (이전에 만든 마커)으로 돌아갈 때 동일한 요청을하고 동일한 데이터를 가져 오는 것입니다 (그러나 분명히 마커를 다시 만들도록하지 않으므로 루프 마침내 모든 마커를 실행합니다.) 지도하고지도 마커의 ID가 동일한 서버에서 데이터 표식 ID를 전송되어 있는지 확인하고 동일한 경우 나는이 방법이 최고라고 생각하지 않는다 그러나 나는 단지) ​​Android 마커를 동적으로로드하는 것이 가장 좋습니다

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; 
         } 
        } 
       } 
      } 

을 루프를 휴식. 또한

  • 서버 화면 경계에 보내고 또한 화면에 보이는 모든 마커 아이디의이 (내가하는 식별자 화면 범위에있는 모든 마커를 선택할 수 있습니다 (적어도 내가 생각하는) 작업을해야 다른 아이디어를 가지고
  • 때마다 안드로이드 응용 프로그램에서 마커를 삭제하고 기본적으로) 개인적으로 나는이 나쁜 솔루션입니다 생각 (서버에서

을 할 때마다 모든 마커를 다시 그래서 그 아이디어 중 어느 것이 최고입니다) 화면 경계 내에없는 ? 다른 아이디어? (내 영어로는 유감입니다)

+0

지도를 이동할 때마다 마커의 위치를 ​​알아야합니까? 처음부터 모든 것을 다운로드하고 마커를 보여줄 수는 없습니까? –

+0

@WaqasAhmedAnsari가 모든 마커를 선행하게하는 것은 총 마커 수가 서버에서 거대 할 때 비효율적입니다. – BhalchandraSW

답변

2

화면에 현재 보이는 마커의 서버 및 ID-s 경계를 보내는 것이 최선의 방법입니다. 그러나 여전히 몇 가지 문제가 있습니다. 화면 범위로 지정한 범위 내에 포함 된 모든 마커를 어떻게 찾을 수 있습니까? 새로운 마커가 서버에 오거나 일부 마커가 삭제되면 어떻게 될까요? 이런 상황에서 유지 보수가 가능한 구조를 제공 할 수 있습니까? 아니면 데이터베이스에서 하나씩 마커에 해당하는 각 지점을 테스트하여 범위에서 위치를 찾았는지 확인하십시오. 이 모든 것을 고려할 때, 포인트 저장 및 쿼리, 즉 마커를 가리키는 위도 및 경도 쌍을 최적화하는 방법을 찾아야합니다. 일반적인 공간 인덱스 방법 중 하나를 사용하여 공간 인덱싱을 수행해야합니다.

공간 인덱싱을위한 여러 가지 방법이 있으며 유스 케이스에 따라 다른 것보다 약간 더 좋을 수 있습니다. 이 시나리오에서 범위를 쿼리해야하므로 긴 이야기를 짧게하려면 쿼드 트리를 구현해야합니다. quadtree는 각 내부 노드가 정확히 네 개의 자식 (북서쪽, 북동쪽, 남서쪽, 남동쪽)을 갖는 트리 데이터 구조로 호출됩니다. 이 구조에 대한 지식이 없으면 한 시간 만에 기본을 이해할 수 있다고 생각하지만 세부적으로 처음부터 자세히 설명하면 나에게 너무 많은 시간을 낭비하게됩니다. 따라서 quadtree에 대한 구현 세부 사항을 건너 뜁니다. 이미이 구조를 내가 할 수있는 것보다 훨씬 잘 설명하는 여러 출처가 있습니다. 오픈 소스 라이브러리를 쉽게 찾을 수 있습니다.

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; 
} 
1

스토어의 모든 눈에 보이는 :

난 단지 이전 화면에 이미있는 사람을 제외한 화면 경계의 범위 내에서 나타나는 모든 포인트를 찾기 위해 쿼드 트리에 대한 의사 틱 자바 방법을 제공합니다 목록에있는 마커 또는 로컬 DB 또는 일부 장소에 존재하지 않는 경우 목록의 기존 마커를 반복합니다. 서버로부터의 요청

1

HashSet<MarkerOptions>을 확장하면 MarkerOptions이 추가 될 때지도에 추가 할 수 있습니다.

class MarkerSet extends HashSet<MarkerOptions> { 
    @Override 
    public boolean add(MarkerOptions markerOptions) { 

     boolean didAdd = super.add(markerOptions); 

     if(didAdd) { 
      mMap.addMarker(markerOptions); 
     } 
     return didAdd; 
    } 
} 

지도 활동에 LatLngBounds 개체를 유지 관리합니다.이 LatLngBounds 객체는 이미 서버에서 데이터를 요청한 경계를 저장합니다.

지도의 카메라가 이동하면 서버에 요청하지 않고 경계를 늘리지 않으면 현재 경계에 새 경계가 있는지 확인하고 서버를 요청하지 않습니다.

mMap.setOnCameraMoveListener(new GoogleMap.OnCameraMoveListener() { 
    @Override 
    public void onCameraMove() { 

     LatLngBounds currentBounds = mMap.getProjection().getVisibleRegion().latLngBounds; 

     if (mBounds == null) { 
      mBounds = currentBounds; 
      // Perform server request and get markers passing in currentBounds 
      // Following to be performed in server request's callback 
      MarkerOptions markerOptions = new MarkerOptions(); 
      // set marker options here 
      mMarkerSet.add(markerOptions); 

     } else { 

      if (!(mBounds.contains(currentBounds.northeast) || mBounds.contains(currentBounds.southwest))) { 
       mBounds = mBounds.including(currentBounds.northeast); 
       mBounds = mBounds.including(currentBounds.southwest); 

       // Perform server request and get markers passing in currentBounds 
       // Following to be performed in server request's callback 
       MarkerOptions markerOptions = new MarkerOptions(); 
       // set marker options here 
       mMarkerSet.add(markerOptions); 
      } 

     } 
    } 
}); 

currentBounds에 대한 서버 요청을 항상 호출해야합니다. currentBoundsmBounds이 겹치는 경우 currentBounds을 줄이면이 ​​알고리즘을 향상시킬 수 있습니다.

가정하는 것은

여기에 가정은 카메라 이동, currentBoundsmBounds이 약간 떨어질 때주의하시기 바랍니다. 그렇지 않으면 새 마커가로드되지 않습니다. 이미지를 참조하여 사용자가 녹색 영역에서 주황색으로 이동하면 mBounds 값은 파란색 직사각형이므로 흰색 영역은 포함되지 않습니다. 그러나 실제로는 카메라를 완벽하게 가로 또는 세로로 이동하는 것이 쉽지 않습니다. 이로 인해 서버 방법이 호출되고 탐색되지 않은 영역에 대한 새 마커가로드됩니다. 이 도움이

How mBounds will be aggregated?

희망. :)

관련 문제