Top 50 Flutter Interview Questions and Answers

Commonly asked Flutter interview questions, from fundamentals to advanced concepts.

1.What is Flutter?

Flutter is Google's open-source UI toolkit for building natively compiled applications for mobile, web, and desktop from a single codebase.

  • Uses the Dart programming language.
  • Renders its own UI directly (via the Skia/Impeller graphics engine) rather than using native platform widgets, giving pixel-perfect consistency across platforms.

2.What is Dart?

Dart is the programming language used by Flutter, developed by Google.

  • Object-oriented, statically typed, with strong support for asynchronous programming (async/await, Future, Stream).
  • Compiles to native machine code (for mobile/desktop) or JavaScript (for web), and supports hot reload during development.

3.What is the difference between Flutter and React Native?

Both enable cross-platform mobile development, but with different architectures:

  • Flutter: renders its own widgets directly via a graphics engine, giving highly consistent UI across platforms; uses Dart.
  • React Native: renders using actual native platform components via a JavaScript bridge; uses JavaScript/TypeScript.
  • Flutter generally offers more consistent visuals and performance; React Native offers closer integration with native look-and-feel by default.

4.What is a Widget in Flutter?

A Widget is the basic building block of a Flutter UI — everything in Flutter, from a button to the entire screen layout, is a widget.

  • Widgets are immutable — describing what the UI should look like given the current state, not directly manipulating the UI themselves.
  • Flutter rebuilds the widget tree efficiently whenever state changes, using a diffing algorithm to update only what's necessary.

5.What is the difference between StatelessWidget and StatefulWidget?

Both are base classes for building widgets, differing in whether they hold mutable state:

  • StatelessWidget: immutable — has no internal state that changes over time; rebuilds only when its parent passes new data.
  • StatefulWidget: maintains a mutable State object that can change over the widget's lifetime, triggering a rebuild via setState().
class Counter extends StatefulWidget {
  @override
  State<Counter> createState() => _CounterState();
}

6.What is the setState() method used for in Flutter?

setState() notifies the Flutter framework that a StatefulWidget's internal state has changed, triggering a rebuild of that widget.

setState(() {
  count++;
});
  • Without calling setState(), changing a state variable directly won't update the UI, since Flutter wouldn't know to rebuild.

7.What is the Widget Tree in Flutter?

The Widget Tree is the hierarchical structure of all widgets composing a Flutter UI, from the root app widget down to individual buttons and text elements.

  • Flutter uses this tree (along with the parallel Element Tree and RenderObject Tree) to efficiently determine what needs to be redrawn when state changes.

8.What is the BuildContext in Flutter?

BuildContext represents a widget's location within the widget tree, providing access to ancestor widgets and services (like themes, navigation, and media queries).

Widget build(BuildContext context) {
  final theme = Theme.of(context);
  ...
}
  • Passed into every widget's build() method, essential for accessing inherited data further up the tree.

9.What is Hot Reload in Flutter, and how does it differ from Hot Restart?

Both speed up development iteration, but differently:

  • Hot Reload: injects updated source code into the running Dart VM without losing app state, near-instantly reflecting UI/logic changes.
  • Hot Restart: fully restarts the app, resetting all state, but still faster than a full rebuild/reinstall.

10.What is the difference between MaterialApp and CupertinoApp in Flutter?

Both are top-level app widgets, styled for different platforms:

  • MaterialApp: implements Material Design, Google's design language (used on Android and cross-platform apps by default).
  • CupertinoApp: implements iOS-style design, mimicking Apple's Human Interface Guidelines.
  • Both provide app-level configuration like theming, routing, and localization.

11.What are the main layout widgets in Flutter (Row, Column, Stack)?

Flutter provides several core layout widgets:

  • Row: arranges children horizontally.
  • Column: arranges children vertically.
  • Stack: overlays children on top of each other, positioned absolutely (useful for badges, overlays).
Column(children: [Text('Title'), Row(children: [Icon(Icons.star), Text('5.0')])])

12.What is the difference between Container and SizedBox in Flutter?

Both size/wrap a child widget, but differ in purpose:

  • Container: a versatile widget supporting padding, margin, decoration (borders, background color), and sizing all in one.
  • SizedBox: a lightweight widget that only enforces a fixed width/height — more efficient when you don't need Container's extra styling features.

13.What are Keys in Flutter, and why are they important?

Keys help Flutter identify widgets uniquely across rebuilds, especially when widgets of the same type change position or are added/removed from a list.

ListView(children: [
  ListItem(key: ValueKey(item.id), item: item),
]);
  • Without proper keys, Flutter may incorrectly preserve or reset state when list items are reordered.

14.What is the difference between GlobalKey and local Key (like ValueKey) in Flutter?

Both identify widgets, but at different scopes:

  • Local Keys (ValueKey, ObjectKey): distinguish sibling widgets within the same parent, mainly for correct diffing during rebuilds.
  • GlobalKey: uniquely identifies a widget across the entire app, allowing direct access to its State or context from anywhere (e.g., to trigger form validation externally).

15.What is the Flutter widget lifecycle for a StatefulWidget?

A State object goes through several lifecycle methods:

  • initState(): called once, when the state object is created — ideal for one-time initialization.
  • build(): called whenever the widget needs to be rendered/rebuilt.
  • didUpdateWidget(): called when the parent rebuilds this widget with new configuration.
  • dispose(): called when the state object is permanently removed — used to clean up controllers, subscriptions, etc.

16.What is the purpose of the dispose() method in Flutter's State class?

dispose() is called when a State object is permanently removed from the widget tree, used for cleanup.

@override
void dispose() {
  _controller.dispose();
  super.dispose();
}
  • Essential for releasing resources like AnimationController, TextEditingController, or stream subscriptions to avoid memory leaks.

17.What is State Management in Flutter, and why is it needed?

State Management refers to patterns/libraries for sharing and updating application state across widgets, beyond simple local setState().

  • Needed because passing data through many widget layers manually ("prop drilling") becomes unwieldy in larger apps.
  • Popular approaches: Provider, Riverpod, Bloc, GetX, and Flutter's built-in InheritedWidget.

18.What is Provider in Flutter?

Provider is a popular state management package that wraps InheritedWidget with a simpler, more ergonomic API.

ChangeNotifierProvider(
  create: (_) => CartModel(),
  child: MyApp(),
);
// access:
final cart = context.watch<CartModel>();
  • Widely recommended by the Flutter team as a solid default for many apps' state management needs.

19.What is the BLoC pattern in Flutter?

BLoC (Business Logic Component) separates business logic from the UI by using Streams and Sinks — the UI sends events in, and receives state changes out.

  • Promotes a clear separation of concerns and testability, since business logic doesn't depend on Flutter widgets at all.
  • Implemented via the flutter_bloc package in most real-world apps, using Bloc or the simpler Cubit classes.

20.What is an InheritedWidget in Flutter?

InheritedWidget is a low-level Flutter mechanism for efficiently passing data down the widget tree without manually threading it through every constructor.

  • Descendant widgets can access the data via context.dependOnInheritedWidgetOfExactType<T>(), and are automatically rebuilt when the inherited data changes.
  • Forms the foundation that higher-level state management solutions like Provider are built on top of.

21.What is the difference between Provider, Riverpod, and Bloc for state management?

All manage state, with different trade-offs:

  • Provider: simple, built on InheritedWidget, great default choice for small-to-medium apps.
  • Riverpod: a more robust evolution of Provider, compile-safe (no BuildContext needed to read providers), better testability.
  • Bloc: enforces a strict, stream-based event/state pattern — more boilerplate, but very structured and testable for complex, large-scale apps.

22.What are Futures in Dart?

A Future represents a value (or error) that will be available at some point in the future — Dart's equivalent of a JavaScript Promise.

Future<String> fetchData() async {
  final response = await http.get(url);
  return response.body;
}
  • Used extensively for asynchronous operations like network calls or file I/O.

23.What is the difference between async/await and .then() in Dart?

Both handle asynchronous Future results, but with different syntax:

  • async/await: writes asynchronous code in a linear, synchronous-looking style — generally more readable, especially for sequential operations.
  • .then(): chains callbacks onto a Future — can become harder to read when chaining many dependent asynchronous steps.
final data = await fetchData(); // vs.
fetchData().then((data) => print(data));

24.What are Streams in Dart, and how do they differ from Futures?

Both represent asynchronous data, but differently:

  • Future: represents a single asynchronous value that resolves once.
  • Stream: represents a sequence of asynchronous values over time (e.g., real-time data, user input events).
Stream<int> countStream() async* {
  for (int i = 0; i < 5; i++) {
    yield i;
    await Future.delayed(Duration(seconds: 1));
  }
}

25.What is a StreamBuilder widget in Flutter?

StreamBuilder rebuilds part of the UI automatically whenever a given Stream emits a new value.

StreamBuilder<int>(
  stream: countStream(),
  builder: (context, snapshot) => Text('${snapshot.data}'),
);
  • Removes the need to manually manage subscriptions and setState() calls for stream-driven UI updates.

26.What is a FutureBuilder widget in Flutter?

FutureBuilder builds UI based on the state of a Future — showing different widgets while it's loading, when it completes successfully, or if it errors.

FutureBuilder<User>(
  future: fetchUser(),
  builder: (context, snapshot) {
    if (snapshot.connectionState == ConnectionState.waiting) return CircularProgressIndicator();
    return Text(snapshot.data!.name);
  },
);

27.What is the pubspec.yaml file used for in a Flutter project?

pubspec.yaml is the project configuration file, similar to package.json in Node.js.

name: my_app
dependencies:
  flutter:
    sdk: flutter
  http: ^1.0.0
  • Declares the app's dependencies, assets (images/fonts), and metadata (name, version).

28.What are Packages/Plugins in Flutter?

Packages are reusable Dart code libraries (pure Dart logic), while Plugins additionally include platform-specific native code (Android/iOS) to access native APIs.

  • Both are published to pub.dev, Flutter/Dart's package repository.
  • Added to a project via pubspec.yaml and installed with flutter pub get.

29.What is the difference between Navigator.push() and Navigator.pushReplacement() in Flutter?

Both navigate to a new screen, but differ in history handling:

  • Navigator.push(): adds a new route on top of the navigation stack — the user can go back to the previous screen.
  • Navigator.pushReplacement(): replaces the current route with a new one — the previous screen is removed from history, so back navigation skips it.

30.What is Named Routing in Flutter?

Named Routing defines routes by string identifiers rather than direct widget references, centralizing route definitions.

MaterialApp(
  routes: {
    '/home': (context) => HomeScreen(),
    '/profile': (context) => ProfileScreen(),
  },
);
Navigator.pushNamed(context, '/profile');

31.What is the difference between a Stateless and Stateful widget's build() method behavior?

Both define UI via a build() method, but it's triggered differently:

  • StatelessWidget: build() re-runs only when the widget receives new configuration from its parent (i.e., it's rebuilt with new constructor arguments).
  • StatefulWidget: build() re-runs whenever setState() is called on its associated State object, in addition to receiving new configuration.

32.What is the purpose of the const keyword in Flutter widgets?

Marking a widget const tells Flutter the widget (and its properties) will never change, allowing the framework to skip rebuilding it entirely when possible.

const Text('Hello World')
  • A meaningful performance optimization, especially for static parts of the UI that don't depend on any state.

33.What is the difference between MediaQuery and LayoutBuilder in Flutter?

Both help build responsive UIs, but provide different information:

  • MediaQuery: gives information about the entire screen/device (size, orientation, padding for notches).
  • LayoutBuilder: gives the constraints of the immediate parent widget, useful for responsive layouts that depend on available space within a specific part of the UI, not the whole screen.

34.What is a ListView.builder in Flutter, and why is it preferred for long lists?

ListView.builder lazily builds list items on demand as they scroll into view, instead of building all items upfront.

ListView.builder(
  itemCount: items.length,
  itemBuilder: (context, index) => ListTile(title: Text(items[index])),
);
  • Essential for performance with long or infinite lists, since a plain ListView(children: [...]) builds every item immediately, wasting memory/CPU.

35.What is the difference between Expanded and Flexible widgets in Flutter?

Both control how a child fills available space in a Row/Column, but differently:

  • Expanded: forces the child to fill all remaining available space (equivalent to Flexible with FlexFit.tight).
  • Flexible: allows the child to take up up to its share of space, but lets it be smaller if its content doesn't need the full amount (FlexFit.loose, the default).

36.What is Platform Channel in Flutter?

A Platform Channel enables communication between Dart code and native platform code (Kotlin/Java for Android, Swift/Objective-C for iOS).

static const platform = MethodChannel('com.example/battery');
final int result = await platform.invokeMethod('getBatteryLevel');
  • Used when a needed native API/SDK isn't already exposed by an existing Flutter plugin.

37.What is the difference between Debug, Profile, and Release build modes in Flutter?

Flutter apps can be built in three modes, each suited to a different purpose:

  • Debug: includes debugging assertions, hot reload support — slower, larger app size.
  • Profile: close to release performance, but retains some profiling capabilities for performance analysis.
  • Release: fully optimized, no debugging overhead — used for actual app store distribution.

38.What is the purpose of the Flutter DevTools?

Flutter DevTools is a suite of performance and debugging tools for Flutter applications.

  • Includes a widget inspector (visualize the widget tree), performance/timeline view (identify jank), memory view, and network view.
  • Essential for diagnosing performance issues and understanding widget rebuild behavior during development.

39.What is Tree Shaking in Flutter, and why does it matter for release builds?

Tree Shaking removes unused code from the final compiled application, reducing app size.

  • Particularly effective for icon fonts (e.g., only including the specific Material Icons actually used) and unused package code.
  • Automatically applied by the Dart compiler during release builds, not during debug builds.

40.What is the difference between a Local and Global state in a Flutter app?

They differ in scope and lifetime:

  • Local state: relevant to a single widget/screen only (e.g., whether a checkbox is checked) — managed with plain setState().
  • Global (app-wide) state: shared across multiple screens/widgets (e.g., logged-in user, shopping cart) — typically managed via Provider, Riverpod, or Bloc.

41.What is the purpose of the AnimationController in Flutter?

AnimationController drives an animation's progress over time, producing values that other widgets can use to animate properties (opacity, position, size).

final controller = AnimationController(
  duration: Duration(seconds: 1),
  vsync: this,
)..forward();
  • Requires a TickerProvider (usually via SingleTickerProviderStateMixin) to sync with the screen's refresh rate.

42.What is the difference between implicit and explicit animations in Flutter?

Both animate UI changes, but differ in control level:

  • Implicit animations (e.g., AnimatedContainer, AnimatedOpacity): automatically animate between old and new property values whenever they change — simple, minimal code.
  • Explicit animations (using AnimationController + AnimatedBuilder): give full manual control over timing, curves, and triggering — needed for more complex or precisely controlled animations.

43.What is a Sliver in Flutter?

A Sliver is a portion of a scrollable area that can have custom scrolling behavior, used within a CustomScrollView.

CustomScrollView(slivers: [
  SliverAppBar(...),
  SliverList(delegate: ...),
]);
  • Enables advanced scrolling effects, like a collapsing app bar or mixed grid/list layouts within a single scrollable view.

44.What is the difference between Flutter's hot reload and a full app rebuild?

They differ significantly in speed and scope:

  • Hot reload: injects only the changed Dart code into the running app, preserving state — takes about a second.
  • Full rebuild: recompiles the entire app from scratch and reinstalls it — needed for changes to native code, plugin additions, or when hot reload can't apply the change (e.g., changing a main() function).

45.What is the purpose of the flutter_test package?

flutter_test provides utilities for writing widget tests — testing Flutter UI components in a simulated environment without a real device/emulator.

testWidgets('Counter increments', (tester) async {
  await tester.pumpWidget(MyApp());
  await tester.tap(find.byIcon(Icons.add));
  await tester.pump();
  expect(find.text('1'), findsOneWidget);
});

46.What is the difference between Unit tests, Widget tests, and Integration tests in Flutter?

They test at different levels:

  • Unit tests: test individual functions/classes in isolation (pure Dart logic, no UI).
  • Widget tests: test a single widget's UI and behavior in a simulated environment (fast, no real device needed).
  • Integration tests: test the complete app running on a real device/emulator, verifying end-to-end user flows.

47.What is Null Safety in Dart?

Null Safety (introduced in Dart 2.12) makes types non-nullable by default, requiring explicit ? to allow null.

String name = "Alice";   // cannot be null
String? nickname;         // can be null
  • Eliminates a whole class of runtime null-reference errors by catching them at compile time instead.

48.What is the difference between ? and ! operators in Dart null safety?

Both relate to nullable types, but for opposite purposes:

  • ? (nullable type / null-aware access): declares a type as nullable (String?), or safely accesses a member only if the value isn't null (obj?.method()).
  • ! (null assertion operator): tells the compiler "I'm certain this isn't null," bypassing the null check — throws a runtime error if it actually is null.

49.What is the difference between mixins and inheritance in Dart?

Both share code between classes, but differently:

  • Inheritance (extends): a class can extend only one superclass, gaining its full implementation.
  • Mixins (with): a class can apply multiple mixins, adding reusable behavior without the single-inheritance limitation.
class Bird extends Animal with Flying, Swimming {}

50.What is the difference between a Factory Constructor and a regular constructor in Dart?

Both create instances, but with different flexibility:

  • Regular constructor: always creates a new instance of the class it's defined in.
  • Factory constructor: can return an existing cached instance, a subtype, or apply custom logic before returning an object — useful for implementing singletons or complex object creation.
factory Logger() => _instance ??= Logger._internal();