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
95 lines
4.3 KiB
Markdown
95 lines
4.3 KiB
Markdown
# РЕАЛЬНОЕ исправление зависаний карты и кнопок
|
||
|
||
## НАЙДЕНА ИСТИННАЯ ПРИЧИНА!
|
||
|
||
**Главная проблема**: В `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 работает правильно.
|