Irbisa · Cheatsheet

Flutter Fundamentals

Widget tree, StatelessWidget, StatefulWidget, BuildContext

Junior Developer · 24 questions

  1. 01

    What is Flutter, how does it differ from React Native and other cross-platform frameworks, and what are its limitations?

    Flutter is Google's UI toolkit for building mobile, web and desktop apps from one Dart codebase.

  2. 02

    Why does Flutter use Dart rather than JavaScript or Kotlin?

    Dart runs both JIT (in debug, which gives sub-second hot reload) and AOT (in release, which gives fast startup and predictable speed with no interpreter).

  3. 03

    What are the layers of Flutter's architecture (framework, engine, embedder) and what does each one do?

    The framework (Dart) holds widgets, layout, gestures and animation; the engine (C++) runs the Dart runtime and renders frames with Impeller; the embedder is the per-platform host that gives the engine a surface, threads, input and lifecycle events.

  4. 04

    What is the difference between imperative and declarative UI, and why is Flutter called declarative?

    In imperative UI you change existing views step by step (label.setText(...)); in declarative UI you describe what the screen should look like for the current state and the framework works out the changes.

  5. 05

    What does "everything is a widget" mean, and why are padding and opacity separate widgets instead of properties?

    Every piece of UI (a button, but also padding, alignment, a theme or a gesture handler) is a widget: an immutable description of part of the screen, and the app is a tree of them.

    // 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…
  6. 06

    What is the difference between StatelessWidget and StatefulWidget, and why not make every widget stateful?

    StatelessWidget has no data of its own and redraws only when the parent gives it new values.

    // Stateless: a pure function of its constructor argumentsclass GreetingCard extends StatelessWidget {  const GreetingCard({super.key, required this.name});  final String name;   @override…
  7. 07

    What is BuildContext, what does it represent in the tree, and why do you need it?

    BuildContext is a widget's position in the tree; in fact it is that widget's Element.

    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),  );…
  8. 08

    In what order do a State object's lifecycle methods run, from creation to disposal?

    createState → initState → didChangeDependencies → build, then deactivate → dispose.

    class ProfileForm extends StatefulWidget {  const ProfileForm({super.key, required this.name});  final String name;   @override  State<ProfileForm> createState() => _ProfileFormState();…
  9. 09

    What is the difference between main() and runApp(), and when do you need WidgetsFlutterBinding.ensureInitialized()?

    main() is the Dart entry point the engine calls first; runApp() takes your root widget, attaches it to the screen and starts producing frames.

    Future<void> main() async {  WidgetsFlutterBinding.ensureInitialized(); // plugins are called below  await Firebase.initializeApp(    options: DefaultFirebaseOptions.currentPlatform,  );  await SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);…
  10. 10

    What do MaterialApp and Scaffold actually provide, and what breaks without them?

    MaterialApp sits once at the root and supplies what the whole app needs; Scaffold lays out one screen.

    void main() => runApp(const MyApp()); class MyApp extends StatelessWidget {  const MyApp({super.key});   @override…
  11. 11

    What is the difference between hot reload, hot restart, and full restart?

    Hot reload injects the changed code and keeps your app's state; hot restart reloads the code and re-runs main() with all state lost; a full restart stops the app and rebuilds and reinstalls it.

  12. 12

    What is pubspec.yaml for, and what does ^ mean in a dependency version?

    pubspec.yaml is the project manifest: name, version, SDK constraint, dependencies, dev dependencies, and the assets and fonts to bundle.

    name: shop_appdescription: Online store client.publish_to: noneversion: 1.4.0+12          # version name + build number environment:…
  13. 13

    The app runs on mobile but crashes on the web at Platform.isIOS with "Unsupported operation: Platform._operatingSystem". How should a Flutter app branch on platform?

    Platform comes from dart:io, which has no web implementation, so reading Platform.isIOS throws UnsupportedError in a browser.

    // 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';…
  14. 14

    How do you debug a Flutter app, and what is the difference between print, debugPrint and log?

    Debug with IDE breakpoints, Flutter DevTools and logs.

    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…
  15. 15

    What are Flutter's debug, profile and release modes, and how do JIT and AOT compilation fit into them?

    Debug runs your Dart code on a VM with a JIT compiler, so hot reload works but the app is slow and asserts are on.

    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…
  16. 16

    A screen fires its API request from inside build() and hammers the server. Why does build run so often, and where does the call belong?

    build() must be a pure function of the widget's inputs: Flutter calls it again on every change, sometimes many times a second.

    // 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),…
  17. 17

    Should a long build method be split into private _buildHeader() helpers or into separate widget classes?

    Prefer a separate widget class.

    // 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 {…
  18. 18

    A counter is kept as a field on the StatefulWidget itself and setState updates it, but the number keeps resetting. Why?

    The widget object holding that field is thrown away and rebuilt every time the parent rebuilds.

    // 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…
  19. 19

    This screen should greet the user with a dialog when it opens, but it throws instead. What is wrong and how do you fix it?

    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());}

    initState runs before the widget is fully in the tree, so its context cannot read inherited widgets yet, and showDialog needs them (localizations, theme, the Navigator).

  20. 20

    Tick row B in this list, then tap "Remove first", and the tick jumps to C. Why, and what is the fix?

    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'),          ),        ],      );}

    Without keys Flutter matches new widgets to existing elements by type and position.

  21. 21

    Find the bug: in a tablet master–detail layout, picking another user in the list still shows the first user's details.

    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…'),      );}

    initState runs once per State, so _user is loaded only for the first userId.

  22. 22

    Find the bug: after tapping Save, crash reports show an unhandled exception from the save handler.

    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();  }}

    After the await the screen may already be closed: its State is unmounted, context is gone, and ScaffoldMessenger.of(context) throws.

  23. 23

    How does your app find out that it went to the background, and what should you do there?

    Mix WidgetsBindingObserver into your State and Flutter calls didChangeAppLifecycleState whenever the app moves between foreground and background.

    class _PlayerState extends State<Player> with WidgetsBindingObserver {  final _controller = VideoController();   @override  void initState() {    super.initState();…
  24. 24

    A CTO asks whether the next product should be Flutter, Kotlin Multiplatform with Compose Multiplatform, or two native apps. What do you weigh?

    Weigh the team, the existing code, how custom the UI is and how much of the product lives in platform features; raw speed rarely decides it.