Irbisa · Шпаргалка
Основы Flutter
Дерево виджетов, StatelessWidget, StatefulWidget, BuildContext
Что такое Flutter, чем он отличается от React Native и других кроссплатформенных фреймворков и какие у него ограничения?
Почему Flutter использует Dart, а не JavaScript или Kotlin?
Из каких слоёв состоит архитектура Flutter (framework, engine, embedder) и что делает каждый?
В чём разница между императивным и декларативным UI и почему Flutter называют декларативным?
Что значит «всё есть виджет» и почему отступы и прозрачность сделаны отдельными виджетами, а не свойствами?
// Composition: one job per wrapper, and the nesting *is* the layoutclass PriceTag extends StatelessWidget { const PriceTag({super.key, required this.label}); final String label; @override…В чём разница между StatelessWidget и StatefulWidget и почему не сделать все виджеты stateful?
// Stateless: a pure function of its constructor argumentsclass GreetingCard extends StatelessWidget { const GreetingCard({super.key, required this.name}); final String name; @override…Что такое
BuildContext, что он представляет в дереве и зачем он нужен?Widget build(BuildContext context) { return Theme( data: ThemeData.dark(), // wrong: this context sits ABOVE the Theme, so it reads the outer theme child: Text('Hi', style: Theme.of(context).textTheme.bodyLarge), );…В каком порядке вызываются методы жизненного цикла State, от создания до уничтожения?
class ProfileForm extends StatefulWidget { const ProfileForm({super.key, required this.name}); final String name; @override State<ProfileForm> createState() => _ProfileFormState();…В чём разница между
main()иrunApp()и когда нуженWidgetsFlutterBinding.ensureInitialized()?Future<void> main() async { WidgetsFlutterBinding.ensureInitialized(); // plugins are called below await Firebase.initializeApp( options: DefaultFirebaseOptions.currentPlatform, ); await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);…Что на самом деле дают MaterialApp и Scaffold и что ломается без них?
void main() => runApp(const MyApp()); class MyApp extends StatelessWidget { const MyApp({super.key}); @override…В чём разница между hot reload, hot restart и полным перезапуском?
Для чего нужен
pubspec.yamlи что означает^в версии зависимости?name: shop_appdescription: Online store client.publish_to: noneversion: 1.4.0+12 # version name + build number environment:…Приложение работает на мобильных, но в вебе падает на
Platform.isIOSс «Unsupported operation: Platform._operatingSystem». Как во Flutter правильно ветвиться по платформе?// wrong: compiles for web but throws UnsupportedError when it runs// import 'dart:io' show Platform;// final isApple = Platform.isIOS || Platform.isMacOS; import 'package:flutter/cupertino.dart';import 'package:flutter/foundation.dart';…Как отлаживать Flutter-приложение и чем отличаются
print,debugPrintиlog?import 'dart:developer' as developer;import 'package:flutter/foundation.dart'; void onCheckoutFailed(Order order, Object error) { if (kDebugMode) { debugPrint('checkout ${order.id}: $error'); // throttled, safe for long text…Что такое режимы debug, profile и release во Flutter и как с ними связаны JIT- и AOT-компиляция?
flutter run # debug: JIT, hot reload, asserts onflutter run --profile # AOT + tracing, real device onlyflutter run --release # AOT, what users get flutter build apk # build defaults to releaseflutter build appbundle --obfuscate --split-debug-info=build/symbols…Экран отправляет запрос к API прямо из build() и заваливает сервер. Почему build вызывается так часто и куда переносить вызов?
// wrong: a new request on every rebuild@overrideWidget build(BuildContext context) { return FutureBuilder( future: api.loadUser(widget.id), // rebuilt = refetched builder: (context, snap) => UserView(snap.data),…Разбивать длинный build на приватные хелперы
_buildHeader()или на отдельные классы-виджеты?// wrong: helper method; one Element, rebuilt with the whole pageWidget _buildHeader(BuildContext context) => Text('Profile', style: Theme.of(context).textTheme.headlineSmall); // right: widget classes; own Elements, const-able, independently rebuiltclass ProfilePage2 extends StatelessWidget {…Счётчик хранится полем прямо в StatefulWidget, setState его меняет, но значение постоянно сбрасывается. Почему?
// wrong: state on the widget; the field dies with the instanceclass Counter extends StatefulWidget { // analyzer: must_be_immutable Counter({super.key}); int count = 0; // recreated by every parent build @override…Экран должен встречать пользователя диалогом при открытии, но вместо этого падает. Что не так и как это исправить?
class _WelcomeState extends State<Welcome> { @override void initState() { super.initState(); showDialog<void>( context: context, builder: (_) => const AlertDialog(title: Text('Welcome!')), ); } @override Widget build(BuildContext context) => const Scaffold(body: Placeholder());}Отметьте строку B в этом списке, затем нажмите «Remove first», и галочка переезжает на C. Почему и как это исправить?
class _TodoListState extends State<TodoList> { final items = ['A', 'B', 'C']; @override Widget build(BuildContext context) => Column( children: [ // CheckTile is stateful: it keeps its own `checked` bool for (final item in items) CheckTile(label: item), TextButton( onPressed: () => setState(() => items.removeAt(0)), child: const Text('Remove first'), ), ], );}Найдите баг: в планшетной раскладке master–detail выбор другого пользователя в списке по-прежнему показывает данные первого.
class _UserDetailsState extends State<UserDetails> { late Future<User> _user; @override void initState() { super.initState(); _user = widget.repo.loadUser(widget.userId); } @override Widget build(BuildContext context) => FutureBuilder<User>( future: _user, builder: (context, snap) => Text(snap.data?.name ?? 'Loading…'), );}Найдите баг: после нажатия «Сохранить» в отчётах о сбоях появляется необработанное исключение из обработчика сохранения.
class _EditNameState extends State<EditName> { final _name = TextEditingController(); Future<void> _save() async { await widget.api.saveName(_name.text); ScaffoldMessenger.of(context) .showSnackBar(const SnackBar(content: Text('Saved'))); Navigator.of(context).pop(); } @override void dispose() { _name.dispose(); super.dispose(); }}Как приложение узнаёт, что ушло в фон, и что там нужно делать?
class _PlayerState extends State<Player> with WidgetsBindingObserver { final _controller = VideoController(); @override void initState() { super.initState();…CTO спрашивает, на чём делать следующий продукт: на Flutter, на Kotlin Multiplatform с Compose Multiplatform или двумя нативными приложениями. Что вы взвешиваете?