# РЕАЛЬНОЕ исправление зависаний карты и кнопок

## НАЙДЕНА ИСТИННАЯ ПРИЧИНА!

**Главная проблема**: В `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 работает правильно.
