Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как устроена память в Dart
Память в Dart управляется автоматически через сборщик мусора (GC). Понимание её структуры критично для оптимизации производительности приложений Flutter.
Структура памяти
Память в Dart разделяется на несколько областей:
1. Heap (кучи)
Heap — основная область для хранения объектов:
- Young Generation — для новых объектов
- Old Generation — для долгоживущих объектов
- Large Object Space — для больших объектов (строки, списки)
2. Stack (стек)
Stack хранит:
- Локальные переменные
- Параметры функций
- Возвращаемые адреса
- Ссылки на объекты из Heap
Жизненный цикл объекта
1. Создание → объект в Young Generation
↓
2. Молодой GC → выживают → перемещаются в Old Generation
↓
3. Full GC → удаляются неиспользуемые
Сборка мусора (Garbage Collection)
Mark-Sweep-Compact алгоритм
1. Mark (Пометка) — рекурсивно пометить живые объекты
↓
2. Sweep (Метание) — удалить неживые объекты
↓
3. Compact (Уплотнение) — переместить живые объекты в начало
Generational GC
Dart использует поколенческую сборку мусора:
// Молодое поколение (часто собирается)
var temp = [];
for (int i = 0; i < 1000; i++) {
temp.add(i); // Быстро удаляется после цикла
}
// Старое поколение (редко собирается)
static final cache = <String, String>{};
Примеры управления памятью
Проблема: Утечка памяти
// ❌ Плохо — утечка памяти
class MyWidget extends StatefulWidget {
@override
State<MyWidget> createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
Timer? _timer;
@override
void initState() {
super.initState();
// Timer удерживает ссылку на этот widget
_timer = Timer.periodic(Duration(seconds: 1), (_) {
if (mounted) {
setState(() {});
}
});
}
@override
void dispose() {
// ❌ Забыли отменить таймер!
// _timer?.cancel();
super.dispose();
}
}
Решение: Правильная очистка
// ✅ Хорошо — нет утечки
@override
void dispose() {
_timer?.cancel();
_subscription?.cancel();
_controller?.dispose();
super.dispose();
}
Типы данных в памяти
Примитивные типы в Stack
void example() {
int age = 25; // Stack
bool isActive = true; // Stack
double price = 99.99; // Stack
}
Объекты в Heap
void example() {
String name = "Flutter"; // Объект в Heap, ссылка в Stack
List<int> numbers = [1, 2, 3]; // Объект в Heap
Map<String, int> data = {}; // Объект в Heap
}
Оптимизация памяти
1. Переиспользование объектов
// ❌ Создание новых объектов каждый раз
class Painter {
void paint(Canvas canvas) {
final paint = Paint() // Новый объект каждый фрейм!
..color = Colors.blue
..strokeWidth = 2;
canvas.drawLine(Offset(0, 0), Offset(100, 100), paint);
}
}
// ✅ Переиспользование
class Painter {
late final Paint _paint = Paint()
..color = Colors.blue
..strokeWidth = 2;
void paint(Canvas canvas) {
canvas.drawLine(Offset(0, 0), Offset(100, 100), _paint);
}
}
2. Избегание больших временных объектов
// ❌ Плохо — создание большого списка
List<int> getNumbers() {
return List.generate(1000000, (i) => i);
}
// ✅ Хорошо — использование итератора
Iterable<int> getNumbers() {
return Iterable.generate(1000000, (i) => i);
}
3. Очистка ресурсов
class DataFetcher {
StreamSubscription? _subscription;
AnimationController? _controller;
void start() {
_subscription = stream.listen((_) {});
_controller = AnimationController(vsync: this);
}
void stop() {
_subscription?.cancel();
_controller?.dispose();
}
}
Инструменты анализа памяти
DevTools Memory Tab
flutter run --profile
# Откроется DevTools, перейди на Memory вкладку
Dart VM Service
// Проверить размер объектов
print("String size: ${"hello".toString()}");
Важные правила
- Dispose всегда — AnimationController, StreamSubscription, Timer
- Избегай циклических ссылок — объекты не смогут быть собраны
- Используй const для неизменяемых значений
- Ленивая инициализация — создавай объекты только когда нужны
- Профилируй — используй DevTools перед оптимизацией
Память — это то, что часто упускают новички. Правильное её управление делает приложение быстрым, стабильным и приятным для использования.