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