Ответ
Компилятор Dart не выполняет глубоких преобразований для late. Его основная задача — отложить проверку инициализации с момента компиляции на момент выполнения.
Что делает late:
- Отключает проверку на null при компиляции для не nullable-переменной.
- Добавляет runtime-гарантию: При первом чтении переменной среда выполнения проверяет, была ли она проинициализирована. Если нет — выбрасывается
LateInitializationError.
Практическое применение в Flutter/Dart:
class DataService {
// Полезно для зависимостей, которые инжектируются после создания объекта
late final ApiClient _client; // Инициализируем позже в init()
void init(ApiClient client) {
_client = client; // Инициализация
}
Future<void> fetchData() async {
// Первое использование _client. Если init() не вызван — ошибка.
final data = await _client.get('/data');
}
}
class MyWidgetState extends State<MyWidget> {
// Частый кейс: инициализация в initState, использование в build
late final PageController _pageController;
late final ComplexData _cachedData;
@override
void initState() {
super.initState();
_pageController = PageController(); // Инициализация
_cachedData = _heavyCalculation();
}
@override
Widget build(BuildContext context) {
// Гарантированно безопасное использование
return PageView(
controller: _pageController,
children: _cachedData.buildWidgets(),
);
}
}
Важно: late — это не ленивая инициализация. Для ленивой инициализации при первом обращении используйте late в сочетании с присваиванием геттера:
class Settings {
late final SharedPreferences _prefs = _initPrefs();
Future<SharedPreferences> _initPrefs() async => await SharedPreferences.getInstance();
// _prefs инициализируется только при первом чтении
}