0% found this document useful (0 votes)
739 views

Flutter Interview Questions and Answers

This document provides Flutter interview questions and answers for junior, intermediate, and senior developer levels. It contains written coding questions to test technical skills as well as verbal questions to ask during an interview. The questions cover topics like state management, widgets, Dart language fundamentals, and best practices for using packages and plugins.

Uploaded by

Santi Lopez
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
739 views

Flutter Interview Questions and Answers

This document provides Flutter interview questions and answers for junior, intermediate, and senior developer levels. It contains written coding questions to test technical skills as well as verbal questions to ask during an interview. The questions cover topics like state management, widgets, Dart language fundamentals, and best practices for using packages and plugins.

Uploaded by

Santi Lopez
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 20

Flutter Interview Questions and Answers

raywenderlich.com/10971345-flutter-interview-questions-and-answers

1/20
Flutter is a relatively new framework for building cross-platform apps, but its popularity
is rapidly increasing. Employers recognize the benefits of a single code base that lets
them merge two or three teams down to one. The number of jobs for Flutter developers
is on the rise.

In this article, you’ll work through a series of Flutter and Dart job interview questions
and answers.

If you’re a developer who’s looking for a new job, work through each of the questions
below. Try to answer on your own before you look at the answer. This can help you
identify areas where you can strengthen your skills.

If you’re here as a potential employer, browse through the questions to get ideas for
what to ask your candidates.

Everyone else — have fun testing your own Flutter and Dart knowledge! :]

The questions are separated into three levels:

Junior: Suitable for a junior developer in Flutter. You’re familiar with the basics,
and you’ve made a few sample apps.
Intermediate: Suitable for an intermediate developer with a strong interest in how
Flutter and Dart work. You’ve read a lot and experimented even more.
Senior: Suitable for a senior-level developer. This is someone who enjoys
thoroughly exploring the Flutter framework and Dart language and knows how to
manage a project.

At each level, you’ll find two types of questions:

Written questions: Good for emailed or online programming tests, since they
involve writing code.
Verbal questions: Good to ask on a video call or in a face-to-face interview.

While you work through the questions, open your favorite IDE.

Junior Written Questions

Question 1
Given the following class:
2/20
class Recipe {
int cows;
int trampolines;

Recipe(this.cows, this.trampolines);

int makeMilkshake() {
return cows + trampolines;
}
}

Convert makeMilkshake() to a getter called milkshake using the shorthand “fat


arrow” syntax.

If a method contains only a single line of code, you can reduce the number of lines of
code by returning the result using the => syntax:

methodName(parameters) => statement;

Note that you don’t use the keyword return when using => .

The makeMilkshake() conversion would be:

int get milkshake => cows + trampolines;

Question 2
Given the following widget:

class MyWidget extends StatelessWidget {


final personNextToMe = 'That reminds me about the time when I was ten and our neighbor,
her name was Mrs. Mable, and she said...';

@override
Widget build(BuildContext context) {
return Row(children: [
Icon(Icons.airline_seat_legroom_reduced),
Text(personNextToMe),
Icon(Icons.airline_seat_legroom_reduced),
]);
}
}

There is a text overflow on some narrow devices:

3/20
How would you fix this?

Expanded(
child: Text(
personNextToMe,
),
),

Wrapping the Text widget with an Expanded widget tells Row to ignore the Text
widget’s intrinsic width and assign it a width based on the remaining space in the row.

Using more than one Expanded widget in a Row , Column or Flex evenly splits the
space among all the Expanded widgets. Use flex to prioritize space allocations when
there’s more than one Expanded widget.

If you also used the Text widget’s overflow property, then bonus points for you.

Read more about layout constraints in the Flutter docs.

Question 3
Refactor the code below so that the children of Row will wrap to the next line when the
display width is too narrow for them to fit.

class MyWidget extends StatelessWidget {


@override
Widget build(BuildContext context) {
return Row(children: [
Chip(label: Text('I')),
Chip(label: Text('really')),
Chip(label: Text('really')),
Chip(label: Text('really')),
Chip(label: Text('really')),
Chip(label: Text('really')),
Chip(label: Text('really')),
Chip(label: Text('need')),
Chip(label: Text('a')),
Chip(label: Text('job')),
]);
}
}
4/20
All you need to do is replace Row with Wrap .

Read more about the Wrap widget in the Medium article, Flutter Wrap Widget.

Question 4
You’ve declared list1 with var , list2 with final and list3 with const . What’s the
difference between these keywords? Will the last two lines compile?

var list1 = ['I', ' ', 'Flutter'];

final list2 = list1;


list2[2] = 'Dart'; // Will this line compile?

const list3 = list1; // Will this line compile?

When using the var keyword, the Data type is inferred and its value can change. The
following line is equivalent to the first line above, except that you explicitly declare the
data type:

List<String> list1 = ['I', ' ', 'Flutter'];

With final and const , you can’t reassign a new value after the initial assignment.
final values are assigned once at runtime and a const variable value has to be either
known at compile time, set, or hard coded before you run your app.

The third line will compile. You’re not reassigning the list2 list itself, but changing the
value of an item in the third index position (remember, indexes start with 0). Lists are
mutable by default in Dart.

If you tried to do the following, though, it wouldn’t compile because you’re trying to
reassign a final variable:

list2 = ['I', ' ', 'Dart'];

The fourth line will not compile because the value of list1 isn’t assigned until runtime.
Read Dartlang’s article, Const, Static, Final, Oh my!, to learn more.

Question 5
Given the following class:

class Pizza {
String cheese = 'cheddar';
}

How would you make cheese private? How would you make it a global variable?
When should you use globals?

Prefixing a variable with an underscore _ makes it private within the library.


5/20
class Pizza {
String _cheese = 'cheddar';
}

Dart doesn’t have the concept of class private variables. A library is generally a file and a
file can contain multiple classes.

If you want to make a global variable, just move it outside of the class:

String cheese = 'cheddar';

Putting it outside the class makes it a top-level variable, which is available anywhere
you import the file.

Global variables are generally frowned upon because it’s easy to lose track of what’s
changing them. This makes debugging and testing difficult. However, they can be
useful sometimes, like when:

Hacking together a quick demo that you aren’t going to maintain.


Creating Singletons to provide services like a database or network authenticator.
Making const variables to share things like colors, dimensions, styles and
themes. These types of global variables are often stored in a separate file, like
constants.dart, which the libraries then import.

See the Dart language’s library and visibility documentation for more details.

Junior Verbal Questions

Question 1
What’s the difference between hot reload and hot restart?

Hot reload maintains the app state while updating the UI almost instantaneously. Hot
restart, by comparison, takes a little longer because it resets the app state to its initial
conditions before updating the UI. Both of these are faster than doing a full restart,
which requires recompiling the app.

When making significant changes, you need to stop and restart the app. On rare
occasions, you might have to delete the app from your simulator/emulator or device and
reinstall it.

Question 2
What is the difference between StatelessWidget and StatefulWidget ?

StatelessWidget is an immutable class that acts as a blueprint for some part of the UI
layout. You use it when the widget doesn’t change while displaying and, therefore, has
no State .

6/20
StatefulWidget is also immutable, but it’s coupled with a State object that allows you
to rebuild the widget with new values whenever calling setState() . Use
StatefulWidget whenever the UI can change dynamically.

If the state becomes more complex or the same state is in two different widgets, then
you should consider a more sophisticated state management solution.

You can read more about stateless and stateful widgets in the Flutter docs.

Question 3
What is the difference between WidgetsApp and MaterialApp ?

WidgetsApp provides basic navigation. Together with the widgets library, it includes
many of the foundational widgets that Flutter uses.
MaterialApp and the corresponding material library is a layer built on top of
WidgetsApp and the widgets library. It implements Material Design, which gives the
app a unified look and feel on any platform or device. The material library has many
additional widgets that come with it.

You certainly aren’t required to use MaterialApp in your project. You can use
CupertinoApp to make iOS users feel at home, or you can even build your own set of
custom widgets to fit your brand.

Question 4
Can you nest a Scaffold ? Why or why not?

Yes, you can absolutely nest a Scaffold . That’s the beauty of Flutter. You control the
entire UI.
Scaffold is just a widget, so you can put it anywhere a widget might go. By nesting a
Scaffold , you can layer drawers, snack bars and bottom sheets.

7/20
Question 5
When is it appropriate to use packages, plugins or third-party dependencies?

Packages and plugins are great for saving you time and work. There’s no need to solve a
complex problem yourself when someone else has done it already, especially if the
solution is highly rated.
On the other hand, there’s also a danger of being too reliant on third party packages.
They can break, have bugs or even be abandoned. When you need to switch to a new
package down the road, you might have to make huge changes to your code.

That’s why it’s important to isolate packages from your core business logic. You can do
that by creating an abstract Dart class that acts as an interface for the package. Once
you’ve set up that kind of architecture, all you have to do to switch packages is to rewrite
the concrete wrapper class that implements your interface.

Intermediate Written Questions

Question 1

8/20
You’re making a shopping app called RubberBaby, which sells dolls. Unfortunately,
you’ve run into a problem on the order page. If a customer makes one order for blue
dolls and another order for red dolls but then tries to delete the blue doll order, the red
doll order is wrong.

Given only the following code, how would you fix the
RubberBaby buggy buttons?

class OrderPage extends StatefulWidget {


@override
_OrderPageState createState() => _OrderPageState();
}

class _OrderPageState extends State<OrderPage> {


bool isShowing = true;
@override
Widget build(BuildContext context) {
return Column(children: [
RaisedButton(
child: (Text('Delete blue')),
onPressed: () {
setState(() {
isShowing = false;
});
},
),
if (isShowing) CounterButton(color: Colors.blue),
CounterButton(color: Colors.red),
]);
}
}

When you have a stateful widget and something about the widget tree changes, the
framework compares widget types to see what it can reuse.

Since both CounterButton widgets are of the same type, Flutter doesn’t know which
widget to assign the state to. That results in the red button updating with the blue
button’s internal counter state.

To address this, use the key property for each widget. This property adds an ID for the
widget:

CounterButton(
key: ValueKey('red'),
color: Colors.red,
),

By adding key , you’ve uniquely identified the red counter button and Flutter will be
able to preserve its state. You can read more about using keys in the Medium article,
Keys! What are they good for?.

9/20
Question 2
GitHub Jobs has an open API for querying software engineering-related job positions.
The following URL returns a list of remote jobs:

https://jobs.github.com/positions.json?location=remote

Given the following simple data class, in which you only care about the company name
and job title, write a function that returns a Future with a List of Job s. You can
ignore error checking for this question.

class Job {
Job(this.company, this.title);

final String company;


final String title;
}

Since the API returns a list of JSON maps, adding a fromJson constructor to Job will
make your life easier:

class Job {
Job(this.company, this.title);

Job.fromJson(Map<String, dynamic> json)


: company = json['company'],
title = json['title'];

final String company;


final String title;
}

There are a number of packages that you could use to make HTTP requests, but the
Dart team maintains the basic http package. To use it, add the dependency in
pubspec.yaml:

dependencies:
http: ^0.12.1

You import the package and create a function to pull the data from GitHub Jobs in the
background:

10/20
import 'dart:convert';
import 'package:http/http.dart' as http;

Future<List<Job>> fetchJobs() async {


final host = 'jobs.github.com';
final path = 'positions.json';
final queryParameters = {'location': 'remote'};
final headers = {'Accept': 'application/json'};
final uri = Uri.https(host, path, queryParameters);
final results = await http.get(uri, headers: headers);
final jsonList = json.decode(results.body) as List;
return jsonList.map((job) => Job.fromJson(job)).toList();
}

After defining the Uri statement, you make the http.get request, which returns a
JSON string.

Next, using json.decode the JSON results are parsed into a map , which is converted
to a List of Job objects.

Our article, Parsing JSON in Flutter, will teach you more about using a web API,
making models and more advanced JSON parsing.

Question 3
Given a Dart stream that produces an unending series of strings that can be either
salmon or trout :

final fishStream = FishHatchery().stream;


// salmon, trout, trout, salmon, ...

Transform the stream so it returns the string sushi only for the first five instances of
salmon .

The transformed stream looks like this:

final fishStream = FishHatchery().stream;


final sushiStream = fishStream
.where((fish) => fish == 'salmon')
.map((fish) => 'sushi')
.take(5);

If you’d like to play with the code more, here’s the FishHatchery class:

11/20
class FishHatchery {
FishHatchery() {
Timer.periodic(Duration(seconds: 1), (t) {
final isSalmon = Random().nextBool();
final fish = (isSalmon) ? 'salmon' : 'trout';
_controller.sink.add(fish);
});
}

final _controller = StreamController<String>();


Stream<String> get stream => _controller.stream;
}

You can learn more about streams in the Flutter’s team video, Dart Streams — Flutter in
Focus and in the Dart Creating Streams docs.

Question 4
Why would the following code block your Flutter app?

String playHideAndSeekTheLongVersion() {
var counting = 0;
for (var i = 1; i <= 1000000000; i++) {
counting = i;
}
return '$counting! Ready or not, here I come!';
}

Would making it an async function help?

It blocks your app because counting to ten billion is a computationally expensive task,
even for a computer.
Dart code runs inside its own area of memory called an isolate — also known as
memory thread. Each isolate has its own memory heap, which ensures that no isolate
can access any other isolate's state.

Making it an async function wouldn't help, either, because it would still run on the
same isolate.

Future<String> playHideAndSeekTheLongVersion() async {


var counting = 0;
await Future(() {
for (var i = 1; i <= 10000000000; i++) {
counting = i;
}
});
return '$counting! Ready or not, here I come!';
}

The solution is to run it on a different isolate:

12/20
Future<String> makeSomeoneElseCountForMe() async {
return await compute(playHideAndSeekTheLongVersion, 10000000000);
}

String playHideAndSeekTheLongVersion(int countTo) {


var counting = 0;
for (var i = 1; i <= countTo; i++) {
counting = i;
}
return '$counting! Ready or not, here I come!';
}

This would not block your UI.

You can read more about asynchronous tasks and isolates in the Flutter team's video,
Isolates and Event Loops — Flutter in Focus and also in didierboelens.com's article,
Futures — Isolates — Event Loop .

You're also going to get another dose of isolates in the next question.

Intermediate Verbal Questions

Question 1
What is the event loop, and what is its relationship to isolates?

Dart was an early adopter of social distancing. Dart code runs on a single thread called
an isolate. Separate isolates don't hang out together — the most they do is text each
other. In computer-speak, you'd say that isolates don't share any memory and they only
communicate through messages sent over ports.
Every isolate has an event loop, which schedules asynchronous tasks to run. The tasks
can be on one of two different queues: the microtask queue or the event queue.

Microtasks always run first, but they are mainly internal tasks that the developer
doesn't need to worry about. Calling a future puts the task on the event queue when the
future completes.

A lot of new Dart programmers think async methods run on a separate thread.
Although that may be true for I/O operations that the system handles, it isn't the case
for your own code. That's why if you have an expensive computation, you need to run it
on a separate isolate.

Read more about isolates, event loops, and concurrency in the Medium article, Dart
asynchronous programming: Isolates and event loops and Futures — Isolates — Event
Loops.

Question 2
13/20
How do you reduce widget rebuild?

You rebuild widgets when the state changes. This is normal and desirable, because it
allows the user to see the state changes reflected in the UI. However, rebuilding parts of
the UI that don't need to change is wasteful.
There are several things you can do to reduce unnecessary widget rebuilding.

The first is to refactor a large widget tree into smaller individual widgets, each
with its own build method.
Whenever possible, use the const constructor, because this will tell Flutter that it
doesn't need to rebuild the widget.
Keep the subtree of a stateful widget as small as possible. If a stateful widget
needs to have a widget subtree under it, create a custom widget for the stateful
widget and give it a child parameter.

Read more about performance considerations in the Flutter docs.

Question 3
What is BuildContext and how is it useful?

BuildContext is actually the widget's element in the Element tree — so every widget has
its own BuildContext .
You usually use BuildContext to get a reference to the theme or to another widget. For
example, if you want to show a material dialog, you need a reference to the scaffold. You
can get it with Scaffold.of(context) , where context is the build context. of() searches
up the tree until it finds the nearest scaffold.

Read didierboelens.com's article, Widget — State — Context — Inherited Widget , to not


only learn about the build context, but also the stateful widget life cycle and inherited
widgets.

Additionally, our article, Flutter Text Rendering, takes you on a low-level tour of the
Flutter source code, where you'll meet build context, elements and even render objects.

Question 4
How do you talk to native code from within a Flutter app?

Normally you don't need to talk to native code because the Flutter framework or third
party plugins handle it. However, if you do find yourself needing to get special access to
the underlying platform, you can use platform channels.

14/20
One type of platform channel is a method channel. Data is serialized on the Dart side
and then sent to the native side. You can write native code to interact with the platform
before sending a serialized message back. That message might be written in Java or
Kotlin on Android or Objective-C or Swift on iOS.

You don't use platform channels on the web, however, because they're an unnecessary
step.

The second type of platform channel is the event channel, which you use to send a
stream of data from the native platform back to Flutter. This is useful for monitoring
sensor data.

The Flutter docs have more details about platform channels.

Question 5
What types of tests can you perform?

There are three main kinds of tests: unit tests, widget tests and integration tests. Unit
tests are all about checking the validity of your business logic. Widget tests are for
making sure UI widgets have the components that you expect them to. Integration tests
check that your app is working as a whole.
One additional type of test that is not as well known is a golden test. In a golden test,
you have an image of a widget or screen and check to see that the actual widget matches
it.

Learn more about testing in the Flutter Cookbook docs and more on golden tests from
the Medium article, Flutter: Golden tests — compare Widgets with Snapshots.

Also, raywenderlich.com has an article about Flutter unit testing.

Senior Written Questions

Question 1
Demonstrate Dart isolate communication using ports by completing the following steps:

1. Give a function called downloadAndCompressTheInternet() to a new isolate.


2. Have it return the value 42 .

15/20
import 'dart:isolate';

void main() async {


// 1
final receivePort = ReceivePort();
// 2
final isolate = await Isolate.spawn(
downloadAndCompressTheInternet,
receivePort.sendPort,
);
// 3
receivePort.listen((message) {
print(message);
receivePort.close();
isolate.kill();
});
}

// 4
void downloadAndCompressTheInternet(SendPort sendPort) {
sendPort.send(42);
}

In this code, you:

1. Create a port for receiving data from the new isolate.


2. Create a new isolate, give it some work to do and provide it a means to send data
back.
3. Listen for any data message that the new isolate sends, then get rid of the isolate.
4. Send the data back using the port that the main isolate is listening to.

The internet decompression algorithm is still under development. :]

Read Coding With Joe's article, Dart Fundamentals — Isolates, to learn more about
isolate communication.

Question 2
You have two tree data structures, where random integers are nodes in the tree. The
numbers don't have to be unique, nor are they sorted in any logical way. Both trees are
an arbitrary number of levels deep. Write an algorithm to identify any numbers in the
first tree that are not in the second.

Here's an example:

16/20
The algorithm should identify that the number 1 is in the first tree, but not in the
second.

First define the nodes in the tree:

class Node {
int data;
List<Node> children;

Node(this.data, {this.children});
}

Add the logic to search the tree recursively, looking for unique integers:

class UniqueTreeItems {
final Set<int> _uniqueIntegers = HashSet<int>();

Set<int> search(Node tree) {


_addInOrder(tree);
return _uniqueIntegers;
}

void _addInOrder(Node node) {


_uniqueIntegers.add(node.data);
if (node.children == null) return;
for (final child in node.children) {
_addInOrder(child);
}
}
}

Set up the test data:

17/20
final treeOne = Node(1, children: [
Node(4, children: [
Node(10),
Node(12),
]),
Node(3, children: [
Node(3),
Node(10),
Node(1),
]),
]);

final treeTwo = Node(4, children: [


Node(10),
Node(3),
Node(12),
]);

Filter out any integers from Tree 1 that are also in Tree 2:

void main() async {


final uniqueOne = UniqueTreeItems().search(treeOne);
final uniqueTwo = UniqueTreeItems().search(treeTwo);
final answer = uniqueOne.where((element) => !uniqueTwo.contains(element));
answer.forEach(print); // 1
}

The answer is 1 .

Senior Verbal Questions

Question 1
What are the pros and cons of different state management solutions?

While there are countless varieties, some of the more popular state management
solutions include BLoC, ChangeNotifier with Provider, Redux, MobX and RxDart.
These are all appropriate for medium- to large-scale apps; if you're only making a quick
demo app, then a stateful widget is often enough.
Instead of listing the pros and cons of each state management option, it's more useful to
look at the situations where a certain class of solutions is a better fit. For example, for
someone who's overwhelmed with the sheer number of options, it's important to choose
a solution that's easy to grasp, mentally. ChangeNotifier with Provider or MobX would
be a good choice, because it makes sense to directly call methods on the state class in
response to events.

If you're heavily reliant on streams, such as with a Firebase API, then it's natural to
choose a stream-based solution like BLoC or RxDart.

18/20
And if you need undo/redo functionality, then you'd want a solution like BLoC or Redux
that handles immutable state well.

In the end, a lot of it comes down to personal preference. You can find links to more
information about the most popular state management systems in Flutter's' list of state
management approaches.

There are also articles about BLoC and Provider with ChangeNotifier here on
raywenderlich.com.

Question 2
How would you design an app to control an elevator?

This question tests your analytical skills, organization and use of SOLID principles.
Here's one possible answer:

1. First, determine what the core functionality is: things like opening and closing the
doors, moving up and down to different floors, calling for help and coordinating
with other elevators. This is your business logic. Drawing a diagram may help.
2. Implement the business logic in Test Driven Development (TDD) style. That is,
write a failing test, write just enough business logic code to make it pass, refactor
and then do it all again with another test.
3. In the beginning, it doesn't matter if you have physical buttons or a Flutter-
powered touch screen. It doesn't matter what the elevator looks like or where it is.
It doesn't matter what the emergency call system is. You should abstract these
external factors behind interfaces that you can mock out during development.
4. Once you've completed the core logic, you can work on implementing each of the
components that you previously only represented with an interface. For the UI,
you'll need to set up a state management system that takes in events like button
pushes or arrivals and then updates the state, which could result in lighting a
button number or updating a screen. You'll also need to implement the services
that interact with the system for making an emergency call or the hardware that
opens the doors.
5. Safety is obviously extremely important for elevators, so in addition to testing the
core business logic and the various system components in isolation, you'll also
need to do thorough integration testing. For an elevator, that will involve manual
testing by robots and/or humans.

Where to Go From Here?


Congratulations! You made it to the end. Don't feel bad if you didn't know all the
answers. I had to do a lot of research myself while writing them.

19/20
Consider this a jumping-off point. Make note of any areas where you're weak, then do
more research in those areas. Reading through the Flutter documentation and Dart
guides will teach you a lot.

If you're looking to learn more Dart, check out our video course on the fundamentals of
Dart. Also, here at raywenderlich.com we're continuously putting out new content on all
things Flutter.

If you have more interview question suggestions, a better answer, or even a code
challenge, please leave them in the comments below.

Good luck with your job hunt!

Core Concepts Flutter

raywenderlich.com Weekly

The raywenderlich.com newsletter is the easiest way to stay up-to-date on everything


you need to know as a mobile developer.

Sign up now

Get a weekly digest of our tutorials and courses, and receive a free in-depth email
course as a bonus!

Average Rating
5/5

Add a rating for this content


Sign in to add a rating
20 ratings

20/20

You might also like