In the current year, as a mid-level Flutter Engineer, I tried to appear in several physical and remote interviews and got to know about a variety of other concepts apart from my limited knowledge, and on behalf of that I tried to enhance my knowledge further. However, in this blog post, let’s prepare ourselves for the top Flutter Interview questions.
Note: This blog post will cover questions/answers ranging from a just-started-guy to a professional Developer. Here’s a list of questions that I have managed to jot down for my audience.
Table of Contents
Questions & Answers
Q1- Object-Oriented Programming pillars?
1- Abstraction
Hiding the irrelevant information to reduce code complexity and increase efficiency.
Here’s how we can implement abstraction:
abstract class Quotes {
Future<Quote> getQuotes();
}
class MotivationalQuotes extends Quotes {
@override
Future<Quote> getQuotes() async {
///some code
}
}
2- Inheritance
There is no need to shed light on this one, I guess, as Dart is an Object-Oriented Language and always fulfills the concept of inheritance, i.e. extends keyword.
3- Polymorphism
In Polymorphism, an object can take on multiple forms and respond in different ways based on the context it is used in.
In Dart, we can implement this approach in several ways:
By inheritance
A subclass inherits properties from its superclass.
By interface
Dart supports Interface, although it doesn’t have an interface keyword.
Furthermore, we use the implements keyword with the actual properties and methods that a class must possess, such as mixins, etc.
Here’s how we can implement Polymorphism:
class Animal {
void makeSound() {
print('Generic animal sound');
}
}
class Dog extends Animal {
void makeSound() {
print('Bark!');
}
}
class Cat extends Animal {
void makeSound() {
print('Meow!');
}
}
void main() {
Animal animal = new Animal();
Animal dog = new Dog();
Animal cat = new Cat();
animal.makeSound(); // Output: Generic animal sound
dog.makeSound(); // Output: Bark!
cat.makeSound(); // Output: Meow!
}
4- Encapsulation
In Encapsulation, a class must contain all of its methods and declared variables under the access modifier - private
to prevent any unauthorized access while providing a public interface through which an object can interact with it.
Here’s how we can implement Encapsulation:
class Person {
String? _name;
int? _age;
String get name => _name!;
set name(String value) => _name = value;
int get age => _age!;
set age(int value) => _age = value;
void speak() {
print('Hello, my name is $_name, and I am $_age years old.');
}
}
void main() {
var person = Person();
person.name = 'John';
person.age = 30;
person.speak(); // Output: Hello, my name is John, and I am 30 years old.
}
Q2- Difference b/w Listview and Listview builders?
– ListView
A ListView renders objects that are visible on the screen. Let’s look into this via a code snippet:
class MyApp1 extends StatelessWidget {
const MyApp1({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: SafeArea(
child: ListView(
padding: const EdgeInsets.symmetric(horizontal: 2, vertical: 2),
keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.onDrag,
children: [
card,
card,
card,
card,
card,
card,
],
),
),
);
}
Widget get card => Card(
clipBehavior: Clip.hardEdge,
borderOnForeground: true,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 12),
child: Row(
children: [
Column(
children: const [
Text(
"Flutter Test",
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w700),
),
Text(
"Some description",
style: TextStyle(fontSize: 14, fontWeight: FontWeight.w700),
),
],
),
const Spacer(),
Column(
children: [
const FlutterLogo(),
const SizedBox(
height: 10,
),
ElevatedButton(onPressed: () {}, child: const Text("Click"))
],
),
],
),
),
);
}
Furthermore, in the above class, a custom Card widget is rendered under a ListView six
times. Upon running we get,
– ListView.builder / ListView.separator
Both of the above only render those widgets that are visible to the user on the screen.
You might think that you provided the same definition for both. So what’s the difference? Well, on considering ListView, if the card widget had a count of 50 or above, the ListView would have made the frame go high and the chances of the app crashing. Here comes ListView.builder/separator to the rescue, since it renders the other items on scroll only.
Here’s the updated version of it:
class MyApp1 extends StatelessWidget {
const MyApp1({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: SafeArea(
child: ListView.separator(
padding: const EdgeInsets.symmetric(horizontal: 2, vertical: 2),
shrinkWrap: true,
itemCount: 62,
itemBuilder: (context, i) => card,
separatorBuilder: (context, _) => SizedBox(height: 10),
),
),
);
}
Widget get card => CardWidget(),
}
Q3- Single and Multi threads in Dart?
Q4- What are Isolates?
I shall answer Q3-4 in a merged format since it’s relatable. Dart is a single-threaded language, which means it runs on a single isolate, to even perform some heavy operations, whereas, multi-threading means that several processors can make use of a single code base to run them at various execution stages.
Apart from this, we can also run some other computations on other isolates by communicating through different ports.
Q5- What is Asynchronous programming?
It allows other operations to finish once they get executed.
Here’s a detailed tutorial available. Check it out:
Q6- Stream and its types with practical examples?
Streams are a way of handling asynchronous data, a continuous flow of data, by listening to events in real-time
and responding to them.
Dart supports two types of Streams:
– Single Subscription Streams
Consider this code snippet:
final StreamController<int> _streamController = StreamController();
StreamSubscription<int>? _streamSubscription;
@override
void initState() {
// TODO: implement initState
super.initState();
_streamSubscription = _streamController.stream.listen((value) {
debugPrint("Listening value $value");
});
}
ElevatedButton(
onPressed: () {
_streamController.sink.add(22);
_streamController.sink.add(44);
_streamController.sink.add(66);
},
child: const Text("Click"),
)
Each time we press the button, we will see three
values printed on the console.
Additionally, upon unsubscribing from the stream,
ElevatedButton(
onPressed: () {
_streamSubscription!.cancel(); /// unsubscibe
_streamController.sink.add(22);
_streamController.sink.add(44);
_streamController.sink.add(66);
},
child: const Text("Click"),
)
– Broadcast streams
Consider the following code snippet:
final StreamController<bool> _streamController = StreamController();
StreamBuilder<bool>(
stream: _streamController.stream,
initialData: true,
builder: (context, s) => TextFormField(
obscureText: s.data!,
decoration: InputDecoration(
suffixIcon: InkWell(
child: Icon(s.data!
? Icons.visibility_off
: Icons.visibility),
onTap: () {
if (s.data!) {
_streamController.sink.add(false);
} else {
_streamController.sink.add(true);
}
},
),
hintText: 'Password',
),
),
),
A stream controller has been attached to a TextFormField and can toggle passwords to obscure text.
What if we duplicate this one (both attached to the same controller)?
We see the error: Bad State, the stream has already been listened to.
Here comes the use of the Broadcast stream.
We need to take the following into account:
- Create a new stream of the same type
- Assign the existing stream controller as a broadcast
- Attach the Stream with FormFields
Here’s the code snapshot:
final StreamController<bool> _streamController = StreamController();
Stream<bool>? _stream;
@override
void initState() {
// TODO: implement initState
super.initState();
_stream = Stream.value(true);
_stream = _streamController.stream.asBroadcastStream(); /// *imp*
}
@override
Widget build(BuildContext context) {
return StreamBuilder<bool>(
stream: _streamController.stream,
initialData: true,
builder: (context, s) => TextFormField(
obscureText: s.data!,
decoration: InputDecoration(
suffixIcon: InkWell(
child: Icon(s.data!
? Icons.visibility_off
: Icons.visibility),
onTap: () {
if (s.data!) {
_streamController.sink.add(false);
} else {
_streamController.sink.add(true);
}
},
),
hintText: 'Password',
),
),
) x 2
}
Q7- What is the use of Tickers in Flutter?
Flutter uses Tickers to refresh the frame rate.
Mainly used for Animations, as Flutter is quite impressive in its UI module, the re-rendering of the frame looks natural.
However, this callback only works when the widget is visible.
We use SingleTickerProviderStateMixin
to apply Tickers.
Here’s a simple snippet:
import 'package:flutter/material.dart';
class CustomAnimationWidget extends StatefulWidget {
const CustomAnimationWidget({Key? key, required this.child}) : super(key: key);
final Widget child;
@override
State<CustomAnimationWidget> createState() => _CustomAnimationWidgetState();
}
class _CustomAnimationWidgetState extends State<CustomAnimationWidget> with SingleTickerProviderStateMixin {
AnimationController? animationController;
Animation<double>? animation;
@override
void initState() {
// TODO: implement initState
animationController = AnimationController(vsync: this, duration: Duration(milliseconds: 500))..forward();
animation = CurvedAnimation(parent: animationController!, curve: Curves.slowMiddle);
super.initState();
}
@override
void dispose() {
// TODO: implement dispose
animationController!.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return FadeTransition(
sizeFactor: animationController!,
child: widget.child,
);
}
}
Q8- Explain the Factory keyword.
A Factory keyword prevents a class from creating a new instance of itself. Secondly, there are two points to remember when making use of this keyword.
- The return statement is used in the same instance.
- Factory doesn’t support this keyword.
Q9- Why do we need Singleton classes in Flutter?
Singletons are a great concept that lets our class declare only instances of it, also allowing global access.
Furthermore, it is much less talked about and less highlighted, yet a great relief for developers out there.
Consider this class snippet:
class DummyQuotes {
static final DummyQuotes quotes = DummyQuotes._();
DummyQuotes._();
void testMethod() => debugPrint("Just a test...");
}
Q10- Difference b/w Stateless and Stateful Widgets?
Here’s a detailed tutorial available. Check it out:
Q11- How can we pass arguments from child to parent class?
Let’s understand this via code snippets:
class DemoApp extends StatefulWidget {
const DemoApp({Key? key}) : super(key: key);
@override
State<DemoApp> createState() => _DemoAppState();
}
class _DemoAppState extends State<DemoApp> {
String _text = "Parent Widget String";
updateValue(val) => setState(() {
_text = val;
});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Pass Data from Child to Parent"),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
_text,
style: const TextStyle(fontSize: 22, fontWeight: FontWeight.w800),
),
CustomChildWidget(callBack: updateValue),
],
),
),
);
}
}
// Child class
class CustomChildWidget extends StatelessWidget {
const CustomChildWidget({Key? key, required this.callBack}) : super(key: key);
final ValueChanged<String> callBack;
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () => callBack("Updated String"),
child: const Text("Updated"),
);
}
}
In the above snippet, I have created a Stateful Widget class that has:
- A string
- A string function with one argument
In addition, we have a custom child widget
that has an Elevated Button and requires a callback of string type.
Upon running this code, we get:
Q12- Explain the Fluter StatefulWidget Lifecycle.
Here’s a great in-depth article about the Stateful Widget lifecycle. Check it out:
Q13- Difference b/w a package and a plugin?
A package contains only Dart code, whereas a plugin has both Dart and Native code.
One thing interesting here is that:
Q14- Your preferred State Management and why?
This question would surely be asked in the interview.
It depends on the developer himself. Nowadays, many prefer Bloc to Provider or GetX, so choose the one that suits you best.
Q15- Your preferred Architectural Pattern?
This question represents the same answer as above. What’s your choice:
MVVM
MVC
Clean Architecture
It’s time to wrap up this article.
Note: I shall modify this blog post with more questions in the future.
Wrapping Up
Thanks for your precious time.
Hope you enjoyed every bit of it.
So, in this blog, we learned about Top Flutter Interview questions with detailed and short answers, viewed some code snippets and examples, etc.
If you have any sort of questions available, please share them with me in the comments section below. I would love to know that as well.
Link to GitHub Repositories, and YouTube Channel
Read out previous blogs – Click here
Also, read Flutter’s Stateful Widget LifeCycle
I’m very happy to discover this website. I need to to thank you for ones time for this wonderful read!!
I definitely liked every little bit of it and i also have you book marked to see new stuff on your site.
Thank you!
I blog frequently and I seriously appreciate
your content. Your article has truly peaked my interest.
I am going to bookmark your site and keep checking for new information about once a week.
I opted in for your RSS feed too.
Thank you!
It’s really a great and helpful piece of information.
I’m glad that you just shared this useful info with us.
Please keep us up to date like this. Thank you for sharing.
Thank you!