generated from Grigo/AndroidTemplate
feat: новая архитектура UI и расширенная визуализация AIS
Архитектурные улучшения: - Внедрен 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
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
# РЕАЛЬНОЕ исправление зависаний карты и кнопок
|
||||
|
||||
## НАЙДЕНА ИСТИННАЯ ПРИЧИНА!
|
||||
|
||||
**Главная проблема**: В `MapLibreMapImpl.updateOwnVesselPosition()` вызывалось **ТРИ отдельных** `uiHandler.post()` операции:
|
||||
|
||||
```java
|
||||
// СТАРЫЙ КОД - ПРОБЛЕМНЫЙ:
|
||||
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() проблематичен**:
|
||||
```java
|
||||
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**:
|
||||
```java
|
||||
// Новые переменные для 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**:
|
||||
```java
|
||||
@Override
|
||||
public void updateOwnVesselPosition(Vessel vessel) {
|
||||
// Данные обновляются СРАЗУ (не блокирующее)
|
||||
JSONObject feature = buildFeature(...);
|
||||
idToFeature.put("own_vessel", feature);
|
||||
|
||||
// Throttled обновление карты
|
||||
updateMapThrottled(vessel);
|
||||
}
|
||||
```
|
||||
|
||||
### 3. **Батчевое обновление карты**:
|
||||
```java
|
||||
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()
|
||||
|
||||
## Ожидаемый эффект:
|
||||
|
||||
1. **Карта и кнопки перестанут зависать**
|
||||
2. **Доквиджеты продолжат работать** (они не затрагивались)
|
||||
3. **Фоновые процессы не пострадают**
|
||||
4. **Обновления карты станут плавными** вместо лагающих
|
||||
|
||||
**Ключевая диагностика**: Смотрите в логах `"Карта обновлена батчом"` - это означает что throttling работает правильно.
|
||||
Reference in New Issue
Block a user