Ответ
Dart использует продвинутый сборщик мусора (GC), который автоматически управляет памятью. Вот как я с этим работаю в Flutter-приложениях:
Как работает GC в Dart:
class MemoryManagementExample {
// Пример управления памятью в Dart
void demonstrateGarbageCollection() {
// Создаем объекты
var heavyObject1 = _createHeavyObject();
var heavyObject2 = _createHeavyObject();
print('Objects created');
// heavyObject1 становится недостижимым после этой строки
// GC может собрать его в следующем цикле
heavyObject1 = heavyObject2;
// Явно помогаем GC, обнуляя ссылки
heavyObject2 = null;
// Вызываем сборку мусора (в основном для тестирования)
// В продакшене это не нужно делать вручную
// import 'dart:developer';
// debugger();
}
List<String> _createHeavyObject() {
return List.generate(10000, (index) => 'Item $index');
}
}
// Практический пример с StreamController, где важно избегать утечек
class DataBloc {
StreamController<String> _dataController = StreamController.broadcast();
List<StreamSubscription> _subscriptions = [];
void initialize() {
// Подписываемся на поток
final subscription = _dataController.stream.listen((data) {
print('Received: $data');
});
_subscriptions.add(subscription);
}
void dispose() {
// ВАЖНО: закрываем контроллер и отписываемся
// Без этого GC не сможет собрать объекты
for (var subscription in _subscriptions) {
subscription.cancel();
}
_subscriptions.clear();
_dataController.close();
_dataController = null!;
print('Resources disposed, ready for GC');
}
}
Типы сборщиков мусора в Dart:
-
Generational GC (по умолчанию):
- Разделяет объекты на "молодые" и "старые"
- Чаще сканирует молодые объекты
- Меньшие паузы (stop-the-world)
-
Compacting GC:
- Устраняет фрагментацию памяти
- Перемещает объекты в памяти
- Используется для больших хипов
Особенности в Flutter:
class ImageCacheManagement {
// Flutter имеет собственные кэши, которые нужно чистить
void clearImageCache() {
// Очищаем кэш изображений при нехватке памяти
imageCache.clear();
imageCache.clearLiveImages();
}
// Использование WeakReference для избежания утечек
void useWeakReferences() {
final strongRef = SomeObject();
// WeakReference позволяет GC собрать объект,
// даже если на него есть weak-ссылка
final weakRef = WeakReference<SomeObject>(strongRef);
// Проверяем, жив ли еще объект
if (weakRef.target != null) {
print('Object is still alive');
}
}
}
Лучшие практики для работы с GC:
- Закрывайте ресурсы:
StreamController.close(),Timer.cancel() - Избегайте циклических ссылок через
WeakReference - Используйте
constдля создания иммутабельных объектов - Очищайте большие коллекции, когда они не нужны
- Для тяжелых вычислений используйте
Isolate, чтобы не блокировать основной поток
Мониторинг памяти в Flutter DevTools:
- Memory tab показывает использование кучи
- Allocation tracing помогает найти утечки
- Performance overlay показывает влияние GC на FPS