Files
AndroidAisMap/UI_HANG_FIX_SUMMARY.md
T
Grigo b5aee265bc 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
2025-10-02 09:15:33 +03:00

117 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Анализ и исправление зависаний UI в MainActivity
## Выявленные проблемы:
### 1. **Основная причина зависания**: `updateControlPanelPosition()`
- Функция вызывается **слишком часто** (7+ мест вызова)
- Выполняет **дорогие операции в главном потоке**:
- Множественные `getHeight()` вызывают **layout pass**
- `setLayoutParams()` - одна из **самых дорогих операций** в Android UI
- Множество логирования в главном потоке
- Вызывается каждые несколько секунд из-за автоматических обновлений
### 2. **Цепочка блокировок**:
```
coordinatesWidget.updateVessel()
→ invalidate()
→ onDraw()
→ getHeight()
→ onDockResize callback
→ updateControlPanelPosition()
→ setLayoutParams() ← BLOCKING!
```
### 3. **Множественные UI обновления**:
- `messageAgeRunnable` - каждую секунду
- `bottomSheetUpdateRunnable` - каждую секунду
- `timeUpdateRunnable` - каждую секунду
- Все в главном UI потоке без throttling
## Внесенные исправления:
### 1. **Throttling для `updateControlPanelPosition`**:
```java
// Добавлены переменные для throttling
private android.os.Handler controlPanelUpdateHandler;
private Runnable controlPanelUpdateRunnable;
private boolean controlPanelUpdatePending = false;
private static final long CONTROL_PANEL_UPDATE_DELAY = 200; // 200ms throttling
// Переработана функция с оптимизациями
private void updateControlPanelPositionSafe() {
// Проверки на нулевые размеры (избегаем layout pass)
if (compassHeight <= 0) return;
if (coordinatesHeight <= 0) return;
// Изменения только если отличаются от текущих
if (params.topMargin != topMargin || params.bottomMargin != bottomMargin) {
// Применяем изменения
}
}
```
### 2. **Безопасные UI обновления**:
```java
private void updateVesselPositionUI(Vessel vessel) {
if (isFinishing() || isDestroyed()) return; // Защита
runOnUiThread(() -> {
try {
updateUIActivity(); // Обновляем watchdog
// ... безопасные операции
} catch (Exception e) {
Log.e(TAG, "Ошибка в updateVesselPositionUI: " + e.getMessage(), e);
}
});
}
```
### 3. **Дополнительная диагностика**:
```java
// Добавлен счетчик вызовов updateControlPanelPosition
private int controlPanelUpdateCount = 0;
// Улучшен UI Watchdog с диагностикой handler'ов
Log.i(TAG, "UI WATCHDOG: Handler status - " +
"watchdog=" + watchdogActive +
", controlPanelCount=" + controlPanelUpdateCount);
// Принудительная остановка при превышении лимита
if (controlPanelUpdateCount > 50) {
// Останавливаем слишком частые обновления
}
```
### 4. **Очистка ресурсов**:
```java
@Override
protected void onDestroy() {
// Добалена очистка throttling handler'а
if (controlPanelUpdateHandler != null) {
controlPanelUpdateHandler.removeCallbacks(controlPanelUpdateRunnable);
}
}
```
## Ожидаемый результат:
1. **Значительное снижение нагрузки** на главный UI поток
2. **Устранение блокировок** от `setLayoutParams()`
3. **Throttling обновлений** control panel до безопасного уровня
4. **Улучшенная диагностика** для понимания проблем в рантайме
5. **Автоматическое восстановление** при превышении лимитов
## Мониторинг:
Следите за логами:
- `"Control panel updates count: X за последние 10 сек"` - количество обновлений
- `"UI WATCHDOG: Handler status"` - состояние всех handler'ов
- `"Control panel updated: top=X, bottom=Y"` - фактические обновления
## Если проблема остается:
1. Проверьте количество вызовов updateControlPanelPosition
2. Рассмотрите полную отключение тестового обновления coordinatesWidget
3. Увеличьте CONTROL_PANEL_UPDATE_DELAY до 500мс
4. Добавьте дополнительный throttling для BottomSheet обновлений