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
117 lines
4.8 KiB
Markdown
117 lines
4.8 KiB
Markdown
# Анализ и исправление зависаний 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 обновлений
|