or

Flutter Interview Questions

22 questions · From freshers to senior developers

These are the Flutter and Dart questions that come up in real interviews at product companies and service companies alike, grouped by experience level. Each one has a short note on what a good answer covers.

Practise these out loud with AI

Freshers (0–2 years)

Practise this level
  1. 1. What is the difference between a StatelessWidget and a StatefulWidget?

    What they look for: A StatefulWidget keeps mutable state in a separate State object and rebuilds when setState is called. Say when you would choose each, with a simple example.

    Recommended Answer:
    A StatelessWidget is immutableβ€”its properties cannot change once built (e.g., Text, Icon). A StatefulWidget can change dynamically at runtime via an associated State object. When setState() is invoked, Flutter schedules the build() method of the State object to rebuild only the affected widget sub-tree.
    // StatelessWidget Example
    class WelcomeText extends StatelessWidget {
      final String name;
      const WelcomeText({super.key, required this.name});
      @override
      Widget build(BuildContext context) => Text('Hello, $name');
    }
  2. 2. What is BuildContext?

    What they look for: It is the widget's position in the tree, used to look up Theme, MediaQuery, Navigator and providers above it. Bonus: mention checking mounted before using context after an await.

    Recommended Answer:
    BuildContext represents the handle to the location of a widget in the entire Element Tree. It is used to interact with ancestors, such as looking up Theme.of(context), MediaQuery.of(context), or Navigator.of(context). In async methods, always verify 'if (mounted)' before accessing context after an await to avoid crash on disposed widgets.
    Future<void> loadProfile() async {
      final data = await api.fetchUser();
      if (!mounted) return; // Guard against disposed widget
      Navigator.of(context).pushNamed('/profile');
    }
  3. 3. What is the difference between hot reload and hot restart?

    What they look for: Hot reload injects code and keeps state; hot restart re-runs the app and resets state. Changes to main() or initState need a restart.

    Recommended Answer:
    Hot Reload loads code changes into the Dart VM and rebuilds the widget tree while preserving app state (e.g., inputs, scroll position) in sub-seconds. Hot Restart reloads the entire app from scratch, resetting the application state and re-running main() and initState().
  4. 4. What are keys and when do you need them?

    What they look for: Keys preserve state when widgets of the same type move, for example reordering a list. Know ValueKey, ObjectKey and when a GlobalKey is justified.

    Recommended Answer:
    Keys uniquely identify widgets. They are essential when reordering, adding, or removing items from a stateful collection of widgets of the same type. Without keys, Flutter matches widgets by runtimeType and index, causing state to attach to the wrong element.
    // Preserving state in dynamic lists
    ListView.builder(
      itemCount: items.length,
      itemBuilder: (context, i) => TodoItemTile(key: ValueKey(items[i].id), item: items[i]),
    );
  5. 5. What is the difference between final and const in Dart?

    What they look for: const is fixed at compile time and canonicalised; final is set once at runtime. Mention that const widgets are not rebuilt, which helps performance.

    Recommended Answer:
    Both prevent reassignment. However, 'const' variables are compile-time constants (allocated once in canonical memory), whereas 'final' variables are initialized once at runtime. Using 'const' on widgets avoids unnecessary widget rebuilds and boosts rendering performance.
    final currentTime = DateTime.now(); // Runtime
    const defaultPadding = EdgeInsets.all(16.0); // Compile-time
  6. 6. What is the difference between a Future and a Stream?

    What they look for: A Future gives one value later; a Stream gives many values over time. Show how you would use FutureBuilder and StreamBuilder.

    Recommended Answer:
    A Future represents a single asynchronous value or error that will be available once (e.g., an HTTP API response). A Stream represents a continuous sequence of asynchronous events over time (e.g., Firebase real-time updates, WebSocket messages, sensor data).
    Stream<int> counterStream() async* {
      for (int i = 1; i <= 5; i++) {
        await Future.delayed(const Duration(seconds: 1));
        yield i;
      }
    }
  7. 7. Explain the lifecycle of a StatefulWidget.

    What they look for: createState, initState, didChangeDependencies, build, didUpdateWidget, dispose. Say what belongs in initState and what must be cleaned up in dispose.

    Recommended Answer:
    The StatefulWidget lifecycle stages are:
    1. createState(): Creates the mutable state instance.
    2. initState(): Initialises controllers, listeners, or one-off logic.
    3. didChangeDependencies(): Triggers when InheritedWidget / Provider dependencies change.
    4. build(): Renders the widget UI.
    5. didUpdateWidget(): Called when the parent rebuilds with new configuration.
    6. dispose(): Essential cleanup for controllers, streams, and timers to prevent memory leaks.
    @override
    void dispose() {
      _textController.dispose();
      _streamSubscription.cancel();
      super.dispose();
    }
  8. 8. How do you build a layout that works on phones and tablets?

    What they look for: MediaQuery, LayoutBuilder, Flexible and Expanded instead of fixed sizes. Mention testing on at least two screen sizes.

    Recommended Answer:
    Responsive layouts in Flutter are built using MediaQuery (for screen dimensions/orientation), LayoutBuilder (for parent container constraints), and flexible widgets like Expanded, Flexible, AspectRatio, and Wrap instead of hardcoded pixel sizes.
    LayoutBuilder(
      builder: (context, constraints) {
        return constraints.maxWidth > 600 ? DesktopNav() : MobileBottomBar();
      },
    );

Mid-level (2–5 years)

Practise this level
  1. 9. Compare Provider, Riverpod and BLoC. Which would you pick and why?

    What they look for: There is no single right answer. Talk about boilerplate, testability and team size, and justify your choice with a project you worked on.

    Recommended Answer:
    InheritedWidget provides an efficient way to pass data down the widget tree without passing parameters through constructors. When its data changes, only widgets that called dependOnInheritedWidgetOfExactType() are scheduled for rebuild. Provider and Riverpod are built on top of this concept.
  2. 10. How do you handle two API calls that can finish in any order?

    What they look for: Ignore or cancel stale responses so only the latest one updates the UI β€” for example a restartable event transformer in BLoC or a request id check. Mention how you would test it.

    Recommended Answer:
    State management separates business logic from UI rendering, prevents unnecessary rebuilds across screens, enables clean testing, and ensures persistent state transitions across screens. Common approaches include BLoC/Cubit, Riverpod, Provider, and GetX.
  3. 11. What are isolates and when would you use one?

    What they look for: Isolates run Dart code in parallel without shared memory. Use them for heavy CPU work like parsing large JSON, via compute() or Isolate.run, so the UI thread does not drop frames.

    Recommended Answer:
    Dart runs on a single thread event loop with two queues: Microtask Queue (higher priority for internal core tasks) and Event Queue (I/O, timers, user taps, UI events). All asynchronous code runs sequentially without parallel execution unless an Isolate is spawned.
  4. 12. How do you structure a large Flutter app?

    What they look for: Feature-first folders, clear layers (data, domain, presentation), repositories and dependency injection. Explain why the structure helps a team, not just what it is.

    Recommended Answer:
    Isolates are Dart's mechanism for true parallel execution. Unlike OS threads that share memory, each Isolate has its own independent heap and memory space, communicating strictly via message passing (Ports). Use 'compute()' or 'Isolate.run()' for heavy JSON parsing or image processing to prevent UI frame drops (jank).
    // Run heavy task off the UI thread
    final parsedList = await Isolate.run(() => heavyJsonParser(rawString));
  5. 13. How do you handle API errors and show them in the UI?

    What they look for: Map exceptions to typed failures, show a clear message with a retry option, and never let a network error crash the app.

    Recommended Answer:
    1. Const constructors to prevent widget rebuilds.
    2. Use RepaintBoundary on complex animations.
    3. Implement ListView.builder / CustomScrollView with slivers for large lists.
    4. Avoid calling setState() high in the widget hierarchy.
    5. Cache network images and minimize opacity/clip layers.
  6. 14. What is the difference between Navigator 1.0 and GoRouter?

    What they look for: GoRouter is declarative and URL-based, which makes deep links, web URLs and redirects (like auth guards) much simpler.

    Recommended Answer:
    Navigator 1.0 is imperative (push/pop based on a stack). Navigator 2.0 (Router API) is declarative, matching the app's navigation stack to the current URL/state. Router packages like 'go_router' simplify deep linking, web navigation, and route redirection.
  7. 15. How do you test a Flutter app?

    What they look for: Unit tests for logic, widget tests for UI, a few integration tests for key flows. Mention mocking with mocktail and testing blocs with bloc_test.

    Recommended Answer:
    Platform Channels use asynchronous message passing over binary protocols to communicate between Flutter (Dart) and native host code (Kotlin/Swift) via MethodChannel, EventChannel (for continuous data streams), or BasicMessageChannel.
    const platform = MethodChannel('com.example.app/battery');
    final int batteryLevel = await platform.invokeMethod('getBatteryLevel');
  8. 16. How do you store data locally?

    What they look for: shared_preferences for small settings, Hive, Isar or sqflite for structured data, and flutter_secure_storage for tokens.

    Recommended Answer:
    Unit Tests verify isolated functions/models without UI; Widget Tests test a single widget's layout and interaction using WidgetTester; Integration Tests verify the complete app workflow end-to-end on a real device/emulator.
    testWidgets('Counter increments test', (WidgetTester tester) async {
      await tester.pumpWidget(const MyApp());
      await tester.tap(find.byIcon(Icons.add));
      await tester.pump();
      expect(find.text('1'), findsOneWidget);
    });

Senior (5+ years)

Practise this level
  1. 17. How do you find and fix jank in a Flutter app?

    What they look for: Profile in DevTools, check UI versus raster thread times, then fix with const widgets, smaller rebuilds, ListView.builder and RepaintBoundary where it actually helps.

  2. 18. Explain the widget, element and render object trees.

    What they look for: Widgets are cheap immutable configuration, elements hold position and state, render objects do layout and painting. This is why rebuilding widgets is cheap.

  3. 19. How do you reduce app size and startup time?

    What they look for: Split debug info, tree-shake icons, compress images, defer loading of rarely used features, and move heavy initialisation off the startup path.

  4. 20. How do you call native Android or iOS code?

    What they look for: MethodChannel or EventChannel, ideally generated with Pigeon for type safety. Mention threading and error handling on the native side.

  5. 21. How would you set up CI/CD for a Flutter app?

    What they look for: Flavors for dev and prod, automated tests on every pull request, signing handled securely, and Codemagic, GitHub Actions or fastlane for store releases.

  6. 22. How would you design offline-first sync?

    What they look for: Local database as the source of truth, a queue of pending changes, sync when online, and a clear rule for resolving conflicts.

Frequently asked questions

How many rounds are there in a Flutter developer interview?

Usually two to four: a Dart and Flutter basics round, a practical or machine-coding round, an architecture discussion for mid and senior roles, and an HR round.

Do Flutter interviews include DSA questions?

Many product companies ask basic data structures and algorithms. Service companies usually focus more on Flutter, Dart and practical app questions.

What is a Flutter machine-coding round?

You build a small working screen in 60 to 90 minutes β€” for example a list loaded from an API with search, loading and error states. Clean structure matters as much as finishing.

More interview questions