100+ Flutter Interview Questions and Answers

100+ Flutter Questions for Freshers & Experts

1. Flutter Basics (30 Questions)

Q76. How do you make an HTTP GET request in Flutter?
A: Use the http package’s http.get() method to fetch data from a URL and handle the response.

Q77. What is the http package in Flutter?
A: The http package is a Dart library for making HTTP requests (GET, POST, etc.) and handling responses in Flutter apps.

Q78. Write code to fetch data from an API using the http package.
A:

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ApiScreen(),
    );
  }
}

class ApiScreen extends StatefulWidget {
  @override
  _ApiScreenState createState() => _ApiScreenState();
}

class _ApiScreenState extends State<ApiScreen> {
  String _data = 'Loading...';

  Future<void> fetchData() async {
    final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts/1'));
    if (response.statusCode == 200) {
      setState(() {
        _data = jsonDecode(response.body)['title'];
      });
    } else {
      setState(() {
        _data = 'Error fetching data';
      });
    }
  }

  @override
  void initState() {
    super.initState();
    fetchData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('API Example')),
      body: Center(child: Text(_data)),
    );
  }
}

Flutter is an open-source UI toolkit by Google for building natively compiled applications for mobile, web, and desktop from a single codebase using the Dart programming language.

Dart is a client-optimized programming language for apps on multiple platforms. Flutter uses Dart for its fast performance, hot reload feature, and ability to compile to native code.

The main() function is the entry point of a Flutter app. It initializes the app and runs the root widget using runApp().

A widget is a building block of a Flutter UI. Everything in Flutter, like buttons, text, or layouts, is a widget, and they are composed to create the app’s interface.

A StatelessWidget is immutable and doesn’t change its UI after being built (e.g., static text). A StatefulWidget is mutable, allowing UI updates when its state changes (e.g., a counter).

The build() method describes the widget’s UI. It returns a widget tree that Flutter renders on the screen and is called whenever the UI needs to be updated.

Hot reload allows developers to see UI changes instantly without restarting the app, preserving the app’s state. It speeds up development by recompiling only the changed code.

The pubspec.yaml file manages the app’s dependencies, assets, and metadata like name, version, and description. It’s used by the Pub package manager.

The Scaffold widget provides a basic app structure with components like AppBar, Drawer, FloatingActionButton, and Body for building Material Design layouts.

runApp() is a function that starts the Flutter app by rendering the root widget. MaterialApp is a widget that configures the app with Material Design features.

Add the dependency (e.g., http: ^1.2.0) under dependencies in the pubspec.yaml file, then run flutter pub get to fetch it.

BuildContext is an object that holds the location of a widget in the widget tree. It’s used to access theme, navigation, or other inherited widget data.

The setState() method notifies Flutter to rebuild the UI when the state of a StatefulWidget changes, triggering the build() method.

The key property uniquely identifies a widget in the widget tree, helping Flutter efficiently update or reorder widgets during rebuilds.

The Expanded widget makes a child widget take up all available space within a Row, Column, or Flex, distributing space based on its flex property.

The SafeArea widget ensures its child widgets avoid system UI intrusions like notches, status bars, or navigation bars, keeping content visible.

The Container widget is a versatile widget for styling, sizing, and positioning its child with properties like padding, margin, color, and decoration.

async marks a function as asynchronous, allowing it to perform tasks like API calls. await pauses execution until a future completes, returning its result.

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Text('Hello, World!'),
        ),
      ),
    );
  }
}

ThemeData defines the visual style (colors, fonts, etc.) for a Flutter app or widget tree, applied via MaterialApp or Theme widget.

GestureDetector is a widget that detects user gestures like taps, swipes, or drags on its child and triggers callbacks like onTap or onPanUpdate.

A Future represents a value that will be available later, used for asynchronous operations like API calls. It resolves to a value or an error.

Use try-catch with await or the .catchError() method on a Future to handle errors gracefully.

The Column widget arranges its children vertically in a linear layout, stacking them from top to bottom.

The Row widget arranges its children horizontally in a linear layout, placing them side by side.

For a Row or Column widget, you can use the textDirection or verticalDirection property.
Or simply reverse the children list using .reversed.

Example (Row reversed using .reversed):
Row(
children: [Text(“A”), Text(“B”), Text(“C”)].reversed.toList(),
)

Example (Column reversed using verticalDirection):
Column(
verticalDirection: VerticalDirection.up,
children: [Text(“A”), Text(“B”), Text(“C”)],
)

The ListView widget displays a scrollable list of children, either vertically or horizontally, ideal for long lists of items.

Use the Padding widget with the padding property (e.g., EdgeInsets.all(16)) to add space around its child widget.

The AppBar widget creates a top bar in a Scaffold, typically containing a title, actions, and navigation controls.

mainAxisAlignment controls alignment along the primary axis (horizontal for Row, vertical for Column). crossAxisAlignment controls alignment along the perpendicular axis.

2. State Management (25 Questions)

State management is the process of managing and updating an app’s data (state) to reflect changes in the UI, ensuring consistency and responsiveness.

Popular solutions include setState, Provider, Riverpod, BLoC, Redux, and GetX.

The Provider package is a simple state management solution that allows sharing and accessing data across the widget tree using Provider or ChangeNotifier.

setState rebuilds a StatefulWidget’s UI when its state changes, notifying Flutter to call the build() method with updated values.

ChangeNotifier is a class that provides change notification to listeners, commonly used with the Provider package for state management.

BLoC (Business Logic Component) is a state management pattern that separates business logic from UI, using streams to handle state changes.

StreamBuilder listens to a stream and rebuilds its UI whenever the stream emits new data, used in patterns like BLoC.

InheritedWidget is a base class for widgets that share data with descendants in the widget tree, used by state management solutions like Provider.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: CounterApp(),
    );
  }
}

class CounterApp extends StatefulWidget {
  @override
  _CounterAppState createState() => _CounterAppState();
}

class _CounterAppState extends State<CounterApp> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Counter App')),
      body: Center(child: Text('Count: $_counter')),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        child: Icon(Icons.add),
      ),
    );
  }
}

Provider is a simpler, widget-based state management solution. Riverpod is more flexible, supports global providers, and doesn’t rely on BuildContext.

The Consumer widget listens to a Provider and rebuilds only its child when the provider’s data changes, optimizing performance.

FutureBuilder listens to a Future and rebuilds its UI based on the future’s state (loading, data, or error).

ValueNotifier is a simple change notifier that holds a single value and notifies listeners when the value changes.

GetX is a lightweight state management, routing, and dependency injection solution that simplifies app development with minimal boilerplate.

Create a StreamController, add data to its stream, and use StreamBuilder to listen and update the UI based on stream events.

Provider.of<T>(context) retrieves the nearest provider of type T in the widget tree, allowing access to shared data.

Use solutions like Provider, Riverpod, or Redux to manage global state, making data accessible across multiple widgets.

ChangeNotifierProvider listens for changes in a ChangeNotifier and rebuilds dependents. Provider shares static data without listening.

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() => runApp(
      ChangeNotifierProvider(
        create: (_) => Counter(),
        child: MyApp(),
      ),
    );

class Counter with ChangeNotifier {
  int _count = 0;
  int get count => _count;
  void increment() {
    _count++;
    notifyListeners();
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Provider Counter')),
        body: Center(
          child: Consumer<Counter>(
            builder: (context, counter, child) => Text('Count: ${counter.count}'),
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: () => context.read<Counter>().increment(),
          child: Icon(Icons.add),
        ),
      ),
    );
  }
}

BlocBuilder is a widget in the BLoC pattern that rebuilds its UI when the BLoC’s state changes, listening to the BLoC’s stream.

Use scalable solutions like BLoC, Riverpod, or Redux, organize state into modular components, and separate business logic from UI.

The async* keyword defines a function that returns a Stream, used for yielding values asynchronously over time.

ValueListenableBuilder listens to a ValueListenable (e.g., ValueNotifier) and rebuilds its UI when the value changes.

Use selective rebuilds with Consumer, BlocBuilder, or ValueListenableBuilder to update only necessary widgets, avoiding full tree rebuilds.

Dependency injection provides objects (like services or providers) to widgets, making state management modular and testable.

3. Navigation and Routing (20 Questions)

Use Navigator.push() to navigate to a new screen and Navigator.pop() to return to the previous screen.

The Navigator class manages a stack of routes (screens) in a Flutter app, allowing navigation between them.

A Route is an abstraction for a screen or page in a Flutter app, managed by the Navigator for transitions.

Pass data via constructor parameters when pushing a new route with Navigator.push() or use Navigator.pop() with a result.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: FirstScreen(),
    );
  }
}

class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('First Screen')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => SecondScreen(data: 'Hello from First!'),
              ),
            );
          },
          child: Text('Go to Second Screen'),
        ),
      ),
    );
  }
}

class SecondScreen extends StatelessWidget {
  final String data;
  SecondScreen({required this.data});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Second Screen')),
      body: Center(child: Text(data)),
    );
  }
}

Named routing uses string identifiers (e.g., /home) to navigate to routes defined in the MaterialApp’s routes property.

Define routes in MaterialApp’s routes map and use Navigator.pushNamed() to navigate to them.

The onGenerateRoute property in MaterialApp dynamically generates routes based on route names, useful for passing arguments.

Use Navigator.popUntil() with a predicate to pop screens until a specific route is reached.

Navigator.pushReplacement() replaces the current screen with a new one, removing the previous screen from the navigation stack.

Navigator.pushAndRemoveUntil() pushes a new route and removes all previous routes until a condition is met.

Use packages like uni_links or configure platform-specific deep link settings to handle URLs that open specific app screens.

ModalRoute is a route that blocks interaction with previous routes, typically used for dialogs or full-screen pages.

Use PageRouteBuilder with a transitionsBuilder to define custom animations for route transitions.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: FirstScreen(),
    );
  }
}

class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('First Screen')),
      body: Center(
        child: ElevatedButton(
          onPressed: () {
            Navigator.push(
              context,
              PageRouteBuilder(
                pageBuilder: (context, animation, secondaryAnimation) => SecondScreen(),
                transitionsBuilder: (context, animation, secondaryAnimation, child) {
                  return FadeTransition(opacity: animation, child: child);
                },
              ),
            );
          },
          child: Text('Go to Second Screen'),
        ),
      ),
    );
  }
}

class SecondScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Second Screen')),
      body: Center(child: Text('Welcome!')),
    );
  }
}

NavigatorState manages the navigation stack and provides methods like push, pop, and pushNamed for navigation.

Use ModalRoute.of(context) to get the current route and its properties, like arguments or name.

WillPopScope intercepts back button presses, allowing custom logic (e.g., showing a confirmation dialog) before popping a route.

Use packages like GetX or define a global NavigatorState key in MaterialApp to access navigation methods without context.

GoRouter is a modern routing package for Flutter that simplifies navigation with named routes, deep linking, and declarative routing.

4. Networking and API Integration (25 Questions)

Use the http package’s http.get() method to fetch data from a URL and handle the response.

The http package is a Dart library for making HTTP requests (GET, POST, etc.) and handling responses in Flutter apps.

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ApiScreen(),
    );
  }
}

class ApiScreen extends StatefulWidget {
  @override
  _ApiScreenState createState() => _ApiScreenState();
}

class _ApiScreenState extends State<ApiScreen> {
  String _data = 'Loading...';

  Future<void> fetchData() async {
    final response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts/1'));
    if (response.statusCode == 200) {
      setState(() {
        _data = jsonDecode(response.body)['title'];
      });
    } else {
      setState(() {
        _data = 'Error fetching data';
      });
    }
  }

  @override
  void initState() {
    super.initState();
    fetchData();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('API Example')),
      body: Center(child: Text(_data)),
    );
  }
}

JSON is a lightweight data format. Parse it in Flutter using jsonDecode() from the dart:convert library to convert a JSON string to a Dart object.

Check the HTTP response status code and use try-catch blocks to handle exceptions during network requests.

Leave a Reply

Your email address will not be published. Required fields are marked *

Learn, Code, Debug and Grow with Expert Resources from CodeXRush.

Our services