Медленное применение, если количество маркеров увеличивается - PullRequest
0 голосов
/ 13 февраля 2020

На карте OpenStreetMap с osmDroid и osmBonusPack я отображаю маркеры и, щелкая по нему, открывается пузырь, все работает, как я хочу, до определенного количества маркеров. Чем больше маркеров я добавлю на карту, тем менее отзывчивым будет приложение. Например, для 1000 маркеров требуется 6 секунд для отображения меню панели инструментов и столько же для перехода к другому виду деятельности, например простому текстовому отображению. Мой код.

private void creationMarker(GeoPoint arg,
                            String titre,
                            String proximite,
                            String description,
                            String identifiant) {
    double doubleProximite;
    Marker startMarker = new Marker(map);
    startMarker.setPosition(arg);
    startMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);

    InfoWindow infoWindow = new MyInfoWindow(R.layout.bonuspack_bubble_black, map);
    ((MyInfoWindow) infoWindow).setTitre(titre);
    ((MyInfoWindow) infoWindow).setDescription(description);
    ((MyInfoWindow) infoWindow).setSubDescription(identifiant);

    startMarker.setTitle(((MyInfoWindow) infoWindow).getTitre());
    startMarker.setTitle(((MyInfoWindow) infoWindow).getDescription());
    startMarker.setTitle(((MyInfoWindow) infoWindow).getSubDescription());
    startMarker.setIcon(getResources().getDrawable(R.drawable.croix_verte, null).mutate());
    startMarker.setInfoWindow(infoWindow);

    doubleProximite = Double.parseDouble(proximite);
    Polygon circle = new Polygon();
    circle.setPoints(Polygon.pointsAsCircle(arg, doubleProximite));

    int myColorZone, myColorCloture;
    myColorZone = this.getResources().getColor(R.color.SurfaceZoneActive, getTheme());
    circle.setFillColor(myColorZone);     // couleur avec arrière plan transparent
    myColorCloture = this.getResources().getColor(R.color.ClotureActive, getTheme());
    circle.setStrokeColor(myColorCloture);// couleur de la circonférence    
    circle.setStrokeWidth(3);            // épaisseur du trait

    map.getOverlays().add(circle);
    map.getOverlays().add(startMarker);

}

Я использую al oop с базой данных SQL для данных маркера.

Я думаю, чем больше маркеров, тем больше событий должно иметь приложение ручка. Какие решения могут решить мою проблему. Заранее благодарю за ответы

Ответы [ 2 ]

0 голосов
/ 12 марта 2020

прошел месяц, у меня есть решение, я изучил проект https://github.com/MKergall/osmbonuspack в папке

https://github.com/MKergall/osmbonuspack/tree/master/OSMBonusPack/src/main/java/org/osmdroid/bonuspack/clustering есть три файла, которые заинтересовали мне управлять кластеризацией.

  • MarkerClusterer. java
  • RadiusMarkerClusterer. java
  • StaticCluster. java

Благодаря М.Кергаллу и Роману Сидорову, которые создали эти java источники.

Я просто скопировал эти файлы в тестовый проект. Я был вдохновлен методами, которые управляют маркерами для того, чтобы поместить круговые полигоны, кластеризация со стороны работает хорошо, но в зависимости от уровня масштабирования, когда рисуются круглые полигоны, больше нет никакого интереса к кластеризации. Я справился с этой проблемой, управляя рисунками многоугольников с экрана, я рисую то, что есть на экране, то же самое для маркеров. Теперь с 20 000 маркеров и полигонов это только начинает препятствовать отзывчивости приложения, когда раньше оно было около 200. Ниже приведены некоторые фрагменты кода.

Ниже приведены некоторые фрагменты кода.
Основной код активности

  private void getlireDataBaseMarkers() {

bar.setVisibility(View.VISIBLE);
bar.getLayoutParams().height = 6;
bar.requestLayout();

 Thread t = new Thread(){
 public void run() {

   Bundle messageBundle=new Bundle();

   nbrMarker = 0;
   dbMarkers = new DBHelper(MainActivity.this);
   if (dbMarkers.numberOfRows() == 0) {
        return;
    }

   SQLiteDatabase db = dbMarkers.getReadableDatabase();
   Cursor res = db.rawQuery(SqlOrderVisibilite, null);
   res.moveToFirst();

   int qtyMarkers = dbMarkers.numberOfRows();
   bar.setMax(qtyMarkers);
   bar.setProgress(0);

   MyRadiusMarkerClusterer radiusMarkers = new MyRadiusMarkerClusterer(MainActivity.this);
   Double zoom = 15.0;
   radiusMarkers.setMaxPolygonZoomLevel(zoom);

   GeoPoint lePoint = new GeoPoint(0.0, 0.0, 0.0);

   while (!res.isAfterLast() &&
            !isPausing.get() &&
             isRunning.get()) {

        lePoint.setLatitude(res.getDouble(res.getColumnIndex(MARKERS_COLUMN_LATITUDE)));
        lePoint.setLongitude(res.getDouble(res.getColumnIndex(MARKERS_COLUMN_LONGITUDE)));

        Marker startMarker = new Marker(map);
        startMarker.setPosition(lePoint);
        startMarker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
        startMarker.setIcon(getResources().getDrawable(R.drawable.person, null).mutate());

        Polygon circle = new Polygon(map);
        int myColorZone, myColorCloture;
        circle.setPoints(Polygon.pointsAsCircle(lePoint,getRandomDoubleBetweenRange(20,200)));
        myColorZone = MainActivity.this.getResources().getColor(R.color.colorAccent, getTheme());
        circle.setFillColor(myColorZone);
        myColorCloture = MainActivity.this.getResources().getColor(colorPrimary, getTheme());
        circle.getOutlinePaint().setColor(myColorCloture);
        circle.getOutlinePaint().setStrokeWidth(4);

        radiusMarkers.add(startMarker);
        radiusMarkers.add(circle);
        nbrMarker++;

        myMessage = handler.obtainMessage();
        messageBundle.putInt(WRITE_QTY_MARKERS,2); // incrémenter le progress bar
        myMessage.setData(messageBundle);
        handler.sendMessage(myMessage);

        res.moveToNext();
     }
     map.getOverlays().add(radiusMarkers);
     res.close();
     dbMarkers.close();

     myMessage = handler.obtainMessage();
     messageBundle.putInt(WRITE_QTY_MARKERS,1); // afficher le nombre de markers
     myMessage.setData(messageBundle);
     handler.sendMessage(myMessage);

 }
 };
   isRunning.set(true);
   isPausing.set(false);
   t.start();

}

часть кода MyMarkerClusterers

@Override
public void draw (Canvas canvas, MapView mapView,boolean shadow){
        //if zoom has changed and mapView is now stable, rebuild clusters:
        // si le zoom a changé et que mapView est maintenant stable, reconstruisez les groupes
        Double zoomLevel = mapView.getZoomLevelDouble();
        //if (zoomLevel != mLastZoomLevel && !mapView.isAnimating()) {
        if (!mapView.isAnimating()) {
            mClusters = clusterer(mapView);
            pClusters = pclusterer(mapView);
            renderer(mClusters, pClusters, canvas, mapView);
            setmLastZoomLevel(zoomLevel);
        }

        for (MyStaticCluster cluster : mClusters) {
            cluster.getMarker().draw(canvas, mapView, shadow);
        }

        for (MyStaticCluster cluster : pClusters) {
            if (getmLastZoomLevel() > mMaxPolygonZoomLevel) {
                cluster.getPolygon().draw(canvas, mapView, shadow);

            }
        }
    }

часть кода MyRadiusMarkerClusterer

@Override
public ArrayList<MyStaticCluster> clusterer(MapView mapView) {

    ArrayList<MyStaticCluster> clusters = new ArrayList<>();
    convertRadiusToMeters(mapView);
    mClonedMarkers = new ArrayList<>(); //shallow copy
    ArrayList<Marker> mFiltreMarkers = new ArrayList<>(mItems);

    Iterator<Marker> it = mFiltreMarkers.iterator();
    while (it.hasNext()){
        Marker valeur = it.next();
        GeoPoint point = valeur.getPosition();
        // limiter le nombre de Marker suivant l'écran
        if( mapView.getProjection().getNorthEast().getLatitude()  >= point.getLatitude()  &&
            mapView.getProjection().getNorthEast().getLongitude() >= point.getLongitude() &&
            mapView.getProjection().getSouthWest().getLatitude()  <= point.getLatitude()  &&
            mapView.getProjection().getSouthWest().getLongitude() <= point.getLongitude()) {
            mClonedMarkers.add(valeur);
        }
        it.remove();
    }

    while (!mClonedMarkers.isEmpty()) {
        Marker m = mClonedMarkers.get(0);
        MyStaticCluster cluster = createCluster(m,null, mapView);
        clusters.add(cluster);
    }
    return clusters;
}

@Override public ArrayList<MyStaticCluster> pclusterer(MapView mapView) {
    ArrayList<MyStaticCluster> clusters = new ArrayList<>();
    convertRadiusToMeters(mapView);
    pClonedPolygon = new ArrayList<> (); //shallow copy
    ArrayList<Polygon> pFiltrePolygon = new ArrayList<>(pItems);
    Iterator<Polygon> it = pFiltrePolygon.iterator();
        while (it.hasNext()){
            Polygon valeur = it.next();
            GeoPoint point = valeur.getInfoWindowLocation();
            // limiter le nombre de Polygon suivant l'écran
            if( mapView.getProjection().getNorthEast().getLatitude()  >= point.getLatitude()  &&
                mapView.getProjection().getNorthEast().getLongitude() >= point.getLongitude() &&
                mapView.getProjection().getSouthWest().getLatitude()  <= point.getLatitude()  &&
                mapView.getProjection().getSouthWest().getLongitude() <= point.getLongitude()) {
                pClonedPolygon.add(valeur);
            }
            it.remove();
        }

    while (!pClonedPolygon.isEmpty()) {
        Polygon p = pClonedPolygon.get(0);
        MyStaticCluster cluster = createCluster(null,p, mapView);
        clusters.add(cluster);
    }
    return clusters;
}
0 голосов
/ 13 февраля 2020

Маркеры довольно тяжелые или, по крайней мере, когда-то были go, когда у меня были такие же проблемы с производительностью, как и у вас. Возможно, существует потенциал для их оптимизации, но это может означать изменение библиотеки Osmdroid и создание запроса на получение с такими изменениями.

Попробуйте выполнить некоторое профилирование, чтобы убедиться, что проблема не в вашем коде, а в библиотека (https://developer.android.com/studio/profile/cpu-profiler.html).

Обратите внимание на то, как вы читаете данные из базы данных - не делайте этого в главном потоке и не измеряйте, сколько времени потребуется, чтобы убедиться, что это не главная проблема.

Попробуйте SimpleFastPointOverlay от Osmdrid - предполагается, что он оптимизирован для большего числа маркеров (хотя они должны иметь одинаковый значок). Даже если он недостаточно гибок для ваших нужд, попробуйте, чтобы убедиться, что маркеры - настоящая проблема. После этого вы можете просмотреть исходный код и использовать его в качестве учебного материала для реализации собственного пользовательского оверлея.

...