generated from Grigo/AndroidTemplate
b5aee265bc
Архитектурные улучшения: - Внедрен UIRenderingCoordinator с централизованным throttling - Решены проблемы зависания UI через батчинг операций карты - Добавлен VesselPathController для отслеживания маршрутов - Реализован MapLibreMapImpl как альтернатива Яндекс.Картам Визуализация AIS: - Добавлены векторные иконки для всех типов судов - Разделение Class A/B судов с соответствующими иконками - Иконки навигационных статусов (anchor, moored, engine, sail) - Улучшенный CursorOverlay с информацией о судах Производительность: - Throttling UI обновлений (vessel: 500ms, AIS: 1s, paths: 2s) - Устранение утечек Handler объектов - Оптимизация GeoJSON операций в MapLibre
4.3 KiB
4.3 KiB
РЕАЛЬНОЕ исправление зависаний карты и кнопок
НАЙДЕНА ИСТИННАЯ ПРИЧИНА!
Главная проблема: В MapLibreMapImpl.updateOwnVesselPosition() вызывалось ТРИ отдельных uiHandler.post() операции:
// СТАРЫЙ КОД - ПРОБЛЕМНЫЙ:
uiHandler.post(() -> updateOwnVesselPathSource("own_vessel", pathCoords)); // 1
uiHandler.post(() -> updateOwnVesselPredictionSource("own_vessel", vessel)); // 2
uiHandler.post(() -> refreshGeoJson()); // 3
Проблемы создававшие блокировки:
1. Множественные UI операции
Каждое обновление GPS/NMEA вызывало 4 раза updateOwnVesselPosition из AppController:
- Из GPS
onLocationUpdated(2 раза) - Из NMEA
onVesselUpdated(2 раза)
2. Тяжелые операции в UI потоке:
refreshGeoJson()- пересоздание всей GeoJSON каждый разupdateOwnVesselPathSource()- обновление источника с множеством координатupdateOwnVesselPredictionSource()- расчет прогноза
3. reffreshGeoJson() проблематичен:
private void refreshGeoJson() {
JSONObject fc = new JSONObject();
fc.put("type", "FeatureCollection");
JSONArray features = new JSONArray();
for (JSONObject f : idToFeature.values()) { // Итерация по ВСЕМ судам
features.put(f); // Объект преобразуется в JSON
}
fc.put("features", features);
source.setGeoJson(fc.toString()); // Создание большой строки!
}
ВНЕСЕННЫЕ ИСПРАВЛЕНИЯ:
1. Throttling система в MapLibreMapImpl:
// Новые переменные для throttling
private final android.os.Handler mapUpdateHandler = new android.os.Handler(android.os.Looper.getMainLooper());
private Runnable mapUpdateRunnable;
private boolean mapUpdatePending = false;
private static final long MAP_UPDATE_DELAY = 500; // 500ms throttling
2. Переработанный updateOwnVesselPosition:
@Override
public void updateOwnVesselPosition(Vessel vessel) {
// Данные обновляются СРАЗУ (не блокирующее)
JSONObject feature = buildFeature(...);
idToFeature.put("own_vessel", feature);
// Throttled обновление карты
updateMapThrottled(vessel);
}
3. Батчевое обновление карты:
private void updateMapBatched(Vessel vessel) {
uiHandler.post(() -> {
// ВСЕ операции в ОДНОМ UI вызове:
updateOwnVesselPathSource("own_vessel", pathCoords);
updateOwnVesselPredictionSource("own_vessel", vessel);
refreshGeoJson(); // Только один раз!
});
}
4. Убрали дублированные вызовы в AppController:
- Удалили 2 избыточных вызова
updateOwnVesselPosition - Теперь остается только 1 throttled вызов вместо 4 обычных
Результат:
- ✅ Throttling: вместо постоянных обновлений - 1 раз в 500мс
- ✅ Батчинг: вместо 3 отдельных UI вызовов - 1 объединенный
- ✅ Дедупликация: вместо 4 вызовов из AppController - 1 throttled
- ✅ Защита от зависания: cleanup handler'ов в cleanup()
Ожидаемый эффект:
- Карта и кнопки перестанут зависать
- Доквиджеты продолжат работать (они не затрагивались)
- Фоновые процессы не пострадают
- Обновления карты станут плавными вместо лагающих
Ключевая диагностика: Смотрите в логах "Карта обновлена батчом" - это означает что throttling работает правильно.