A cheat sheet to master interviews as a Flutter developer
In the past six months, I’ve been on both sides of the recruiting process: for those who better know me, I often attend interviews to win shyness, and anxiety, and to keep myself updated about the development scene.
I always wanted to live an experience as a developer for a company that wasn’t speaking my mother tongue, so I decided to raise the bar by attending interviews in English.
Once I got a job offer, my former company needed to replace me so I was involved in the recruiting process of selecting a new Flutter developer. This has been an amazing experience because I had the opportunity to meet a lot of candidates and learn many things about the recruiting world as a technical interviewer.
Since January 2022, I attended a dozen of interviews with different companies as I was applying as a Senior Mobile Developer or Technical Lead, and I had the chance to better understand what companies look for in terms of knowledge and skills.
And that’s the purpose of this article: to give you a set of non-mandatory rules you can follow to master your next interviews as a Flutter developer.
Rule number one: Know what you did (and you’re doing)
One of the questions I like to ask, and many companies also like to, is to describe your journey in the company you’re working for, or you’ve worked for. The answers may vary according to the subjects involved in the interview, but if you’re speaking to a technical one, he might expect you to describe how your contribution impacted on the product.
You are allowed to speak about technologies, frameworks, and tools, and I think you must remember at least a bunch of them. One gold question could be related to your favorite set of third-party libraries that you typically use inside your Flutter project: you could mention three to five dependencies that you use in your daily routine as a Flutter developer. If you are not able to answer that question the interviewer may assume that you are not as fluent as expected.
Rule number two: State Management
Flutter has a very easy learning curve. I think this is one of the main drawbacks of this amazing framework because it allows people without any coding background to start creating apps.
Unless you’re applying for some sort of internship program, I think it’s better to master at least one state management. There are plenty of them out there, but please, please, don’t say you use setState only.
Another common mistake people do is to misunderstand the behaviors of the components involved in a state management pattern. Let me give you an example. One of the questions I like to ask the candidate is to tell me what kinds of state management patterns he uses.
I’m confident using Provider.
Let me get this straight to the point. Provider is not a state management pattern. It’s a way of realizing dependency injection in the widget tree by wrapping the InheritedWidget behavior. The component involved in the state management is ChangeNotifier, not certainly Provider!
TL;DR, the same argument is also valid for the GetIt library.
I think this confusion also comes from the official Flutter documentation that provides a list of methods to handle state management, without going deep into the definition.
Rule number three: Asynchronous programming
Flutter is a framework that relies on streams and futures: it mostly uses a reactive programming approach, so knowing how to handle streams and futures is mandatory.
Keep in mind that the interviewer may ask you how Flutter handles multitasking. All of the stuff in Flutter is done in the main thread: if you plan to draw a widget or perform a request to an API, the framework will take care of it. When you need to execute heavy background processes that may involve a lot of CPU or GPU, it’s better you spawn an Isolate. An Isolate is a process that runs separately from the main thread and can communicate with the main one using two ports.
Speaking about streams, probably you won’t be asked to explain how things work under the hood. Just remember the basic stuff like how to listen to it, how to consume it on the UI, and so on. For instance, you may need to show a CircularProgressIndicator as soon as a particular stream hasn’t emitted new events yet, to do that you can use a StreamBuilder. Also, if you need to listen for another stream to invoke other methods in your logic, you can listen to its changes by invoking the .listen() method.
Another tricky question would be to elaborate on the differences between single subscriptions and broadcast streams, or between yield and yield*.
It’s the same for futures. Most of the time you will invoke async methods that return a Future. For instance, you could request some data coming from the internet by querying a REST API. Just make sure you know the differences by invoking a future with or without the await keyword, or how to interact with them on the UI with a FutureBuilder.
Rule number four: Testing
If you’re trying to apply for a well-structured company, writing tests is one of the most important things you need to know. In Flutter there are basically three ways of writing tests:
- Unit tests: they give you the ability to test a small part of the code, typically a fragment that doesn’t interact too much with other logical layers of the application.
- UI tests: they give you the ability to test a finite widget or a screen/page. It’s a specialization of the unit test applied to the UI
- Integration tests: they give you the ability to test larger areas of your application that interacts with each other. Those kinds of tests are more complex and take more time to write, run and debug.
You also need to know how the mocking process works. When you write tests, you need to define boundaries the test doesn’t need to trespass. These boundaries allow you to test only some specific parts of the code.
Imagine you need to test a Repository. Typically a Repository is an abstraction layer that communicates with the lower ones without letting the invoker know which one it is. The lower layers invoked could be a REST API Service or a Data Access Object that reads and writes data to a database instance. In this particular case, you don’t need to test the whole tour, so you will just mock services and DAOs in order to focus on your repository.
Bonus track: Questions
I will leave here you a list of the most common questions I received during my interviewing process and some of them I like to ask candidates:
- What are the differences between Stateless and Stateful Widgets?
- Describe the StatefulWidget lifecycle
- What are LocalKeys and GlobalKeys? How would you use them?
- Can you tell me what is the purpose of the Scaffold widget?
- When would you use the SafeArea widget?
- Do you use any kind of architecture for your projects? Have you ever heard about Clean Code Architecture?
- How do you interact with the native? Do you know how to invoke Java/Kotlin or ObjectiveC/Swift code from Flutter?
- How do you deploy your applications? Have you ever used any kind of automatic tools to run tests or deploy your application like Fastlane?
- How do you manage internationalization in your application?
- How do you navigate across pages? Can you explain what kind of methods you use to navigate across them?
- Modifiers: can you tell me the differences between const, final and late?
- Animations: can you tell me what kinds of animations you can create in Flutter?
- Have you ever created flavors inside your flutter project? Do you use any kind of third-party libraries to do that?