#android #google-maps #google-maps-markers #markerclusterer
#Android #google-карты #google-карты-маркеры #markerclusterer
Вопрос:
Редактировать: показать, что mapManager.filter()
делает метод.
У меня есть приложение для Android с ~ 20 тыс. маркеров, которые рисуются на карте, и с опцией фильтров, поэтому маркеры рисуются и удаляются много. В настоящее время я использую эту библиотеку кластеризации, потому что она более эффективна для отображения большого количества маркеров, чем классическая библиотека карт Google. Но он не поддерживается и не обновлялся с 3 лет, и я не нашел никаких альтернатив.
Вот видео с ошибкой.
Вот мой код, который вызывается, когда я нажимаю на опцию фильтрации в своем приложении:
private void filter(){
//currentMapManager contain all the filters option and also the array list
//of the unfiltered markers (~20,000 markers)
//it's filter method retrieve the current filtering option enable (marker type, and other specs)
//And return markers from the full arraylist that match those filters options.
ArrayList<MarkerModel> filteredList = currentMapManager.filter(currentMapManager.getAllMarkers());
if (clusterManager != null) {
clusterManager.setItems(new ArrayList<>());
clusterManager.onCameraIdle();
clusterManager.setItems(filteredList);
clusterManager.onCameraIdle();
}
Вот mapManager.filter()
метод.
public ArrayList<MarkerModel> filter(List<MarkerModel> currentMarkers) {
ArrayList<Object> filtersArray = filters.getFilters();
/* filtersArray is an array like this :
* ['type', ['typeFilter1', 'typeFilter2'],
* 'date', dateTimestamp,
* 'withPictures', true,
* ....]
*/
return filter(currentMarkers, filtersArray);
}
private ArrayList<MarkerModel> filter(List<MarkerModel> currentMarkers,
ArrayList<Object> fieldsAndValues) {
if (fieldsAndValues.size() % 2 == 1) {
throw new IllegalArgumentException("Missing value in call to filterList().
There must be an even number of arguments that alternate between
field names and values");
} else {
//Here the arraylist that we are returning
ArrayList<MarkerModel> filteredMarkers = new ArrayList<>();
List<Object> argumentList = new ArrayList();
Collections.addAll(argumentList, fieldsAndValues);
if (!currentMarkers.isEmpty()) {
for (int j = 0; j < currentMarkers.size(); j ) {
MarkerModel marker = currentMarkers.get(j);
boolean isInFilter = true;
//Check fieldsAndValue filters...
//If isInFilter stay to true we
filteredMarkers.add(marker);
}
}
return filteredMarkers;
}
}
Я думаю, проблема в том, что библиотека кластеров не должна так сильно перерисовываться, и в какой-то момент она перестала читать и работать с массивом элементов 20k.
Я просмотрел всю ветку forks этой библиотеки и посмотрел / попытался понять исходный код библиотеки, но не нашел никакого решения моей проблемы…
Если вам нужна другая часть моего исходного кода, чтобы понять больше, скажите мне, я добавлю ее.
Большое спасибо, если вы можете мне помочь, я много боролся с этой проблемой…
Комментарии:
1. Одна вещь, которую я замечаю в реализации библиотеки
setItems
, заключается в том, что она пытается отменить любой активныйmQuadTreeTask
, но не ждетonCancelled
(вероятно, потому, что это усложняет реализацию). Однако при быстром увеличении / уменьшении масштаба это может выявить проблему, поскольку каждая нерешенная задача работает с одним и тем же квадродеревом. Подробнее обcancel
этом здесь: developer.android.com/reference/android/os /. …2. С учетом сказанного, похоже, что он использует однопоточный исполнитель, что означает, что вышеупомянутое не будет применяться, поскольку может быть запущена только одна задача — все еще неправильная реализация, хотя — тем более, что вы не знаете, когда
setItems
на самом деле завершено (с точки зрения клиента) — например, что, если вы изменитеfilteredList
— делаетвернитеcurrentMapManager.filter
клон или новый список (обратите внимание, что инициализацияfilteredList
в опубликованном выше коде ничего не делает), поскольку вы просто перезаписываете.3. Просто имейте в виду в своем коде: когда вы вызываете
setItems
, и он возвращает, это на самом деле не выполняется из-за реализации asynctask — это действительно должно обеспечить «полный обратный вызов».4. Спасибо, Энди! Я собираюсь попытаться реализовать это
onComplete
с помощью alistener
и сообщу вам, решит ли это проблему или нет. Для инициализацииfilteredList
это потому, что у меня есть больше кода с некоторыми if / else для моих параметров глобальной фильтрации (и не связанных сcurrentMapManager
), но я удалил много строк для упрощения здесь.currentMapManager.filter
верните новый список, который я отредактировал в своем вопросе, чтобы немного показать, что он делает (снова упрощенный)5. Может оказаться трудным ввести обратный вызов, поскольку
mQuadTreeTask
по завершении появляется вторая задача (ClusterTask
) для инициирования обновления кластеризации. Также обратите внимание, чтоonCameraIdle
инициирует aClusterTask
, что означает, что выsetItems
инициируете кластеризацию, за которой немедленно следует вторая кластеризацияonCameraIdle
. Я бы рекомендовал создать простой проект карты с маркерами 100k и различными «отфильтрованными» случаями, используя ваш код и наблюдая за результатами — я могу сделать это сам и опубликовать результаты. Также добавьте краткое объяснение видео относительно того, что вы считаете неправильным — для ясности.