Какие способы отладки (дебаггинга) в Flutter вы знаете?

Ответ

В Flutter я использую несколько подходов для отладки, в зависимости от ситуации:

1. Базовые методы для быстрой проверки:

// Простой вывод в консоль
print('Current state: $state');

// Для длинных строк без обрезки
debugPrint(jsonEncode(complexObject));

// Проверка условий только в debug-сборке
assert(user != null, 'User must be initialized');

2. Инструменты разработчика:

  • Flutter DevTools — основной инструмент для инспекции:
    • Widget Inspector — визуальное дерево виджетов и их свойства
    • Performance View — анализ рендеринга и jank
    • Network Profiler — мониторинг HTTP-запросов
    • Memory Profiler — отслеживание утечек памяти

3. Точки останова и пошаговая отладка в IDE (VS Code/Android Studio):

void fetchData() {
  final url = 'https://api.example.com/data'; // Брейкпоинт здесь
  final response = await http.get(Uri.parse(url));
  // Шаг за шагом можно проверить response
}

4. Структурированное логирование через пакеты:

dependencies:
  logger: ^2.0.0
final logger = Logger();
logger.d('Debug message');
logger.w('Warning: API rate limit接近');
logger.e('Error fetching data', error: e, stackTrace: s);

5. Командная строка Flutter:

# Просмотр логов устройства
flutter logs

# Запуск с флагами отладки
flutter run --verbose

# Профилирование производительности
flutter run --profile

6. Кастомные утилиты для сложных случаев:

// Отладка перестроений виджетов
class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    debugPrint('MyWidget rebuilt'); // Отслеживаем лишние rebuild
    return Container();
  }
}

// Визуальные маркеры для UI
debugPaintSizeEnabled = true; // Показывает границы виджетов

На практике я обычно начинаю с print() для быстрой проверки, затем перехожу к DevTools для анализа производительности, и в сложных случаях использую комбинацию брейкпоинтов и структурированного логирования.

Ответ 18+ 🔞

А, ну вот, Flutter и отладка — это как пытаться объяснить кошке, зачем ей нужен унитаз. Вроде бы всё должно работать, а она всё равно в тапки срет. Но ладно, давай разберёмся, как не сойти с ума.

1. Для начала, простейшие штуки, чтобы просто понять, что вообще происходит:

// Старый добрый принт, классика жанра
print('А что у нас в стейте? А вот что: $state'); // Выводит, но может обрезать, если строка длинная

// Поэтому для длинных JSON или объектов лучше так
debugPrint(jsonEncode(complexObject)); // Этот, бля, не обрежет, вывалит всё

// А это — наш сторожевой пёс, который кусает только в отладочной сборке
assert(user != null, 'Ты чё, мудила, user не проинициализирован!'); // Упадет с криком, если условие false

Это как постучать по двигателю — слушаешь, не стучит ли что. Быстро и грязно.

2. Нормальные инструменты — Flutter DevTools. Это уже не молоток, а целая мастерская. Запускаешь, подключаешься к приложению и:

  • Widget Inspector — тут ты можешь тыкать в интерфейс на телефоне и смотреть, какой именно виджет там отображается, со всеми его свойствами. Прямо как рентген для UI. Охуенно, когда непонятно, почему кнопка не нажимается или текст не виден.
  • Performance View — тут снимаешь профиль и смотришь, где у тебя фризы (jank). Графики, таймлайны — видно, какой кусок кода или анимация жрёт ресурсы, как не в себя.
  • Network Profiler — все твои HTTP-запросы как на ладони. Что ушло, что пришло, сколько времени заняло. Незаменимо, когда бэкенд тормозит или прилетает не тот ответ.
  • Memory Profiler — следит, не течёт ли память. Чтобы приложение через полчаса работы не накрылось медным тазом.

3. Точки останова и пошаговая отладка прямо в IDE (VS Code или Android Studio). Вот это уже серьёзно. Ставишь брейкпоинт на подозрительной строке — и приложение останавливается.

void fetchData() {
  final url = 'https://api.example.com/data'; // <-- Поставил тут точку, запустил
  final response = await http.get(Uri.parse(url)); // Приложение встанет ДО выполнения запроса
  // А дальше можно шагать (Step Over, Step Into) и смотреть, что в response прилетело, какие переменные какие значения имеют.
}

Прямо как в детективе — замираешь на месте преступления и рассматриваешь все улики.

4. Когда принтов уже не хватает, а DevTools — это овердохуища, подключаем структурированное логирование. В pubspec.yaml добавляешь:

dependencies:
  logger: ^2.0.0

А в коде:

final logger = Logger();
logger.d('Это просто отладочное сообщение, всё ок');
logger.w('Предупреждение: лимит запросов к API близок, чувак!');
logger.e('Всё пошло по пизде!', error: e, stackTrace: s); // Для ошибок, с трейсом

Красиво, с уровнями, с фильтрацией. Уже не бардак в консоли, а читаемый лог.

5. Не забываем про командную строку Flutter, там тоже полезного дохуя:

# Смотрит логи прямо с подключённого девайса/эмулятора
flutter logs

# Запускает приложение в режиме максимальной болтливости
flutter run --verbose  # Выдаст тонну инфы, иногда слишком тонну

# Запуск в профилировочном режиме (для замера производительности, не для дебага UI)
flutter run --profile

6. И наконец, кастомные фишки для особо ебучих случаев:

// Допустим, подозреваешь, что виджет перестраивается чаще, чем ты моргаешь
class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    debugPrint('MyWidget опять перестроился, ёпта!'); // Смотри в консоль, как часто это выводится
    return Container();
  }
}

// Включить визуальные подсказки (границы виджетов и т.д.)
debugPaintSizeEnabled = true; // Всё приложение покроется рамочками — сразу видно слои и размеры

Итог, чувак: Обычно всё начинается с тупого print(), чтобы понять, в какую сторону вообще копать. Потом, если проблема в UI или производительности — врубаешь DevTools и там уже ковыряешься. Если же логика сложная, гоняешь пошагово с брейкпоинтами. А для долгосрочного мониторинга или сложных фич уже настраиваешь нормальное логирование через logger. Главное — не пытаться всё делать одним способом, инструментов дохуя, и каждый для своего случая.