Menu Close

Top 20 Flutter Interview Questions and Answers for Job Seekers in 2023- Devduniya

5/5 - (2 votes)

Flutter is a popular open-source framework for building high-performance, cross-platform mobile apps. As the demand for Flutter developers continues to grow, it’s important to be prepared for interviews and understand the key concepts and skills that are commonly tested. In this blog post, we’ll take a look at some of the most frequently asked Flutter interview questions and provide sample code examples to help you understand the answers. Whether you’re a seasoned developer looking to switch to Flutter or just starting out, this guide will help you feel more confident and prepared for your next interview.

Flutter is a mobile app development framework created by Google. It uses the Dart programming language and allows for the creation of high-performance, visually attractive apps for both iOS and Android platforms. Here are some common interview questions and answers for a Flutter developer position:

Q1. What is Flutter and how does it differ from other mobile app development frameworks?

Answer: Flutter is an open-source mobile app development framework created by Google. It uses the Dart programming language and allows for the creation of high-performance, visually attractive apps for both iOS and Android platforms. It differs from other frameworks such as React Native and Xamarin in that it uses its own widgets and does not rely on native components.

Q2. How does the Flutter framework handle state management?

Answer: Flutter uses a built-in widget called the InheritedWidget to handle state management. This widget allows for the sharing of data across multiple widgets in the app. Additionally, popular state management libraries such as Provider and Bloc can be used for more advanced state management.

Q3. Can you give an example of how to create a simple Flutter app?

Answer:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("My Simple Flutter App"),
        ),
        body: Center(
          child: Text("Hello World!"),
        ),
      ),
    );
  }
}

This is a basic example of how to create a simple Flutter app that displays “Hello World!” on the screen. The main() function runs the app and calls the MyApp widget, which returns a MaterialApp with a Scaffold containing an AppBar and a Text widget in the body.

Q4. How does Flutter handle layout and design?

Answer: Flutter uses a flexible layout system known as “widgets”. Each widget is a self-contained unit that can handle its own layout and design. The widgets are composed together to create the final layout and design of the app. Additionally, Flutter also provides a rich set of pre-designed widgets that can be easily customized to meet the specific needs of an app.

Q5. How would you access a REST API using Flutter?

Answer: There are several libraries that can be used to access REST APIs in Flutter, such as http and dio. Here’s an example of how to use the http package to make a GET request to a REST API:

import 'package:http/http.dart' as http;
void getData() async {
  var response = await http.get('https://jsonplaceholder.typicode.com/todos/1');
  print(response.body);
}

This code uses the http.get() function to make a GET request to the specified URL and stores the response in a variable. The response’s body can then be printed or parsed as needed.

Q6. How do you handle navigation in Flutter?

Answer: Flutter provides a built-in navigation system called Navigator. The Navigator widget manages a stack of Route objects and provides methods to push and pop routes. Here’s an example of how to navigate to a new page:

import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Home"),
      ),
      body: Center(
        child: RaisedButton(
          child: Text("Go to Next Page"),
          onPressed: () {
            Navigator.of(context).push(
              MaterialPageRoute(builder: (context) => NextPage()),
            );
          },
        ),
      ),
    );
  }
}

class NextPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Next Page"),
      ),
      body: Center(
        child: Text("Welcome to the Next Page"),
      ),
    );
  }
}

This code defines a HomePage widget that contains a button that, when pressed, navigates to a NextPage widget using the Navigator.of(context).push() method.

Q7. How do you handle user input in Flutter?

Answer: Flutter provides a variety of widgets for handling user input, such as TextField, Checkbox, and Radio. Here’s an example of how to use a TextField to gather user input:

import 'package:flutter/material.dart';
class MyForm extends StatefulWidget {
  @override
  _MyFormState createState() => _MyFormState();
}

class _MyFormState extends State<MyForm> {
  final _formKey = GlobalKey<FormState>();
  String _name;

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Column(
        children: <Widget>[
          TextFormField(
            validator: (value) {
              if (value.isEmpty) {
                return 'Please enter your name';
              }
              return null;
            },
            onSaved: (value) => _name = value,
            decoration: InputDecoration(labelText: 'Name'),
          ),
          RaisedButton(
            onPressed: () {
              if (_formKey.currentState.validate()) {
                _formKey.currentState.save();
                print("Name: $_name");
              }
            },
            child: Text('Save'),
          ),
        ],
      ),
    );
  }
}

This code defines a MyForm widget that contains a Form widget with a TextFormField for gathering the user’s name. The validator function is used to ensure that the input is not empty, and the onSaved function is used to save the input to a variable. A RaisedButton is also provided to submit the form and print the saved name to the console.

Q8. How do you handle async operations in Flutter?

Answer: Flutter uses the async and await keywords for handling async operations. Here’s an example of how to use the Future class to fetch data from an API:

import 'package:http/http.dart' as http;
Future<String> fetchData() async {
  var response = await http.get('https://jsonplaceholder.typicode.com/todos/1');
  return response.body;
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: FutureBuilder<String>(
            future: fetchData(),
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return Text(snapshot.data);
              } else if (snapshot.hasError) {
                return Text("Error: ${snapshot.error}");
              }
              return CircularProgressIndicator();
            },
          ),
        ),
      ),
    );
  }
}

This code defines a fetchData() function that makes an API call and returns the response body as a Future. The FutureBuilder widget is used to handle the returned Future and display the data, an error message, or a loading indicator depending on the state of the future.

Q9. How does Flutter handle animation?

Answer: Flutter provides a powerful animation framework for creating rich, smooth, and interactive animations. The core of the framework is the Animation class, which represents an animation that is continuously updated over a given duration. Flutter also provides a variety of pre-built animation widgets, such as AnimatedContainer, AnimatedOpacity, and AnimatedCrossFade that can be used to easily add animations to your app. Additionally, you can use the AnimationController class to create more complex animations by controlling the animation’s state and animation curve. Here’s an example of how to use the AnimatedContainer widget to animate the size of a container:

import 'package:flutter/material.dart';
class MyAnimation extends StatefulWidget {
  @override
  _MyAnimationState createState() => _MyAnimationState();
}

class _MyAnimationState extends State<MyAnimation> {
  double _width = 100;
  double _height = 100;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: AnimatedContainer(
          width: _width,
          height: _height,
          duration: Duration(seconds: 1),
          curve: Curves.easeInOut,
          child: FlutterLogo(),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          setState(() {
            _width = 200;
            _height = 200;
          });
        },
        child: Icon(Icons.play_arrow),
      ),
    );
  }
}

This code defines a MyAnimation widget that contains an AnimatedContainer widget with a FlutterLogo child. The AnimatedContainer is given an initial width and height of 100, and when the user taps the floating action button, the width and height are changed to 200 and the animation runs for 1 second using the ease-in-out curve.

Q10. How would you handle localization and internationalization in Flutter?

Answer: Flutter provides a built-in Localizations framework for handling localization and internationalization. The framework allows you to create localized versions of your app’s text, messages, and other resources. The Intl package can also be used to format dates, times, and numbers according to the conventions of different locales. Here’s an example of how to use the Localizations framework to change the app’s locale:

import 'package:flutter/material.dart';
import 'package:my_app/localization.dart';
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      localizationsDelegates: [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        MyAppLocalizationsDelegate(),
      ],
      supportedLocales: [
        const Locale('en', 'US'),
        const Locale('fr', 'FR'),
      ],
      home: HomePage(),
    );
  }
}

This code sets up a LocalizationsDelegate and specifies the supported locales for the app. The MyAppLocalizationsDelegate class is responsible for loading the localized resources and providing them to the app.

To create the localized resources, you can use the intl_messages.arb file. This file contains the key-value pairs of the localized text. You can use the intl package to generate the dart file from the arb file:

flutter pub pub run intl_translation:extract_to_arb --output-dir=lib/l10n lib/localization.dart
flutter pub pub run intl_translation:generate_from_arb --output-dir=lib/l10n --no-use-deferred-loading lib/localization.dart lib/l10n/intl_*.arb

In this way, you can handle localization and internationalization in Flutter by specifying the locales and loading the localized resources. It’s important to note that this is just a basic example and in real-world applications, more complex and dynamic localization and internationalization strategies may be needed.

Q11. How would you handle form validation in Flutter?

Answer: Flutter provides a built-in Form widget for handling form validation. The Form widget can be used to create a form and validate the input fields. The TextFormField widget, specifically, allows you to validate the text input by providing a validator function. Here’s an example of how to use the Form and TextFormField widgets to create a simple login form:

import 'package:flutter/material.dart';

class LoginForm extends StatefulWidget {
  @override
  _LoginFormState createState() => _LoginFormState();
}

class _LoginFormState extends State<LoginForm> {
  final _formKey = GlobalKey<FormState>();
  String _email;
  String _password;

  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Column(
        children: <Widget>[
          TextFormField(
            validator: (value) {
              if (value.isEmpty) {
                return 'Please enter your email';
              }
              return null;
            },
            onSaved: (value) => _email = value,
            decoration: InputDecoration(labelText: 'Email'),
          ),
          TextFormField(
            validator: (value) {
              if (value.isEmpty) {
                return 'Please enter your password';
              }
              return null;
            },
            onSaved: (value) => _password = value,
            decoration: InputDecoration(labelText: 'Password'),
            obscureText: true,
          ),
          RaisedButton(
            onPressed: () {
              if (_formKey.currentState.validate()) {
                _formKey.currentState.save();
                print("Email: $_email, Password: $_password");
              }
            },
            child: Text('Submit'),
          ),
        ],
      ),
    );
  }
}

This code defines a LoginForm widget that contains a Form widget with two TextFormField widgets for the email and password. The validator function is used to ensure that the input is not empty, and the onSaved function is used to save the input to a variable. The obscureText property is used to hide the password input. A RaisedButton is also provided to submit the form and print the saved email and password to the console.

Q12. What is the difference between StatelessWidget and StatefulWidget in Flutter?

Answer: In Flutter, StatelessWidget and StatefulWidget are two different types of widgets that are used to build the user interface of an app.

StatelessWidget is a widget that will not change during its lifetime. These widgets are created with a single build method and they will only be created once. Example:

class MyTextWidget extends StatelessWidget {
  final String text;

  MyTextWidget({required this.text});

  @override
  Widget build(BuildContext context) {
    return Text(text);
  }
}

StatefulWidget, on the other hand, can change during its lifetime. These widgets hold mutable state and are created with two separate build methods, one for creating the initial widget and another for rebuilding it. Example:

class MyCounterWidget extends StatefulWidget {
  @override
  _MyCounterWidgetState createState() => _MyCounterWidgetState();
}

class _MyCounterWidgetState extends State<MyCounterWidget> {
  int _counter = 0;

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

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Counter: $_counter'),
        RaisedButton(
          onPressed: _incrementCounter,
          child: Text('Increment'),
        ),
      ],
    );
  }
}

It’s important to note that the setState is only available in the StatefulWidget and it’s used to notify the framework that the internal state of this widget has changed, and the framework should rebuild this widget.

Q13. How do you implement a custom font in Flutter?

Answer: In Flutter, you can use the Text widget to display text with a custom font. To use a custom font, you first need to add the font file to your project’s assets.

Here is an example of how to do this:

No.1 Create a new folder in the root of your Flutter project called assets.
No.2 Add your custom font file(s) to the assets folder.

In your pubspec.yaml file, add the following lines under assets:

assets:
  - assets/your_custom_font.ttf

No.3. To use the custom font in your Text widget, you can use the style property and set the fontFamily to the name of your custom font file:

Text(
  "Hello, World!",
  style: TextStyle(fontFamily: 'your_custom_font'),
)
Note:

If your custom font has different font files for different styles (e.g. bold, italic), you should add them to your assets and use the fontWeight and fontStyle properties of the TextStyle class to set the desired style.
You also need to run flutter pub run flutter_launcher_icons:main command before running the application.

Q14. How do you handle screen transitions in Flutter?

Answer: In Flutter, you can handle screen transitions using the Navigator widget. The Navigator provides a stack-based navigation system, where you can push and pop routes (i.e. screens) from the stack. Here’s an example of how you can use the Navigator to navigate between two screens:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: '/',
      routes: {
        '/': (context) => FirstScreen(),
        '/second': (context) => SecondScreen(),
      },
    );
  }
}

class FirstScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('First Screen'),
      ),
      body: Center(
        child: RaisedButton(
          onPressed: () {
            Navigator.pushNamed(context, '/second');
          },
          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: RaisedButton(
          onPressed: () {
            Navigator.pop(context);
          },
          child: Text('Go back to First Screen'),
        ),
      ),
    );
  }
}

In this example, the MyApp class defines the initial route to be ‘/’, which maps to the FirstScreen widget. The FirstScreen widget contains a button that, when tapped, calls Navigator.pushNamed(context, ‘/second’) to navigate to the second screen. The second screen is defined in the SecondScreen widget and contains a button that, when tapped, calls Navigator.pop(context) to go back to the first screen.

You can also use Navigator.push() and Navigator.pop() to navigate between routes in addition to Navigator.pushNamed() and Navigator.pop(). The push method takes a MaterialPageRoute as an argument, which is a type of Route that animates the new screen into view. For example:

    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => SecondScreen()),
    );

Q15. How do you implement push notifications in a Flutter app?

Answer: To implement push notifications in a Flutter app, you will need to use a package called firebase_messaging. Here’s an example of how to set it up:

Add the firebase_messaging package to your pubspec.yaml file:

dependencies:
  firebase_messaging: ^7.0.3

Import the package in your main.dart file:

import 'package:firebase_messaging/firebase_messaging.dart';

Create a new instance of FirebaseMessaging:

final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();

In the initState method of your StatefulWidget, call configure to set up your app to receive push notifications:

@override
void initState() {
  super.initState();
  _firebaseMessaging.configure(
    onMessage: (Map<String, dynamic> message) async {
      print("onMessage: $message");
    },
    onLaunch: (Map<String, dynamic> message) async {
      print("onLaunch: $message");
    },
    onResume: (Map<String, dynamic> message) async {
      print("onResume: $message");
    },
  );
}

Request permission to receive push notifications:

_firebaseMessaging.requestNotificationPermissions(
  const IosNotificationSettings(
    sound: true,
    badge: true,
    alert: true,
    provisional: true,
  ),
);

Finally, retrieve the token for the device:

String token = await _firebaseMessaging.getToken();
print("FirebaseMessaging token: $token");

This is a basic example of how to set up push notifications in a Flutter app using the firebase_messaging package. You can customize the behavior of the app when it receives a notification by modifying the onMessage, onLaunch, and onResume callbacks.

Make sure you have to follow the firebase setup process and configure your app to use it, if you haven’t done it already.

Q16. How would you optimize the performance of a Flutter app?

Answer: There are several ways to optimize the performance of a Flutter app, some include:

Lazy loading

Only load the widgets and assets that are visible on the screen, rather than loading everything at once.
Example:

ListView.builder(
  itemBuilder: (context, index) {
    if (index >= someData.length) {
      return null;
    }
    return SomeWidget(someData[index]);
  },
),

Caching

Store frequently used data in memory so that it can be quickly accessed without having to fetch it again.
Example:

class MyImageProvider extends ImageProvider<MyImageProvider> {
  @override
  ImageStreamCompleter load(MyImageProvider key) {
    return MultiFrameImageStreamCompleter(
      codec: _loadAsync(key),
      scale: key.scale,
      informationCollector: (StringBuffer information) {
        information.writeln('Image provider: $this');
        information.write('Image key: $key');
      },
    );
  }
}

Profiling

Use the Flutter performance tooling to identify bottlenecks and track performance over time.

Avoid using setState() unnecessarily

Use setState() only when it is necessary to update the state of the widget, otherwise it can cause unnecessary rebuilds and slow down the app.
Example:

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

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

Use const for all values that will not change

The const keyword tells the Flutter framework that a value will not change, allowing it to be more efficiently handled.
Example:

const double myHeight = 100.0;

Note that the optimization process for a flutter app is an ongoing task and can be done by combination of above methods and other methods that suit your specific app requirements.

Q17. How do you implement in-app purchases in a Flutter app?

Answer: In-app purchases in a Flutter app can be implemented using the in_app_purchase package. Here’s an example of how to use the package to make a simple in-app purchase:

First, add the in_app_purchase package to your pubspec.yaml file:

dependencies:
  in_app_purchase: ^0.3.3+1
Next, import the package in your Dart file:
import 'package:in_app_purchase/in_app_purchase.dart';
Initialize the package by calling InAppPurchaseConnection.enablePendingPurchases() and InAppPurchaseConnection.instance.isAvailable():
await InAppPurchaseConnection.enablePendingPurchases();
bool available = await InAppPurchaseConnection.instance.isAvailable();
if (!available) {
  print('In-app purchases are not available on this device.');
  return;
}

Use the InAppPurchaseConnection.instance.queryProductDetails() method to retrieve information about the in-app purchase you want to make:

final ProductDetailsResponse response = await InAppPurchaseConnection.instance.queryProductDetails(<String>['your_product_id']);
final ProductDetails product = response.productDetails.first;
Use the InAppPurchaseConnection.instance.buyNonConsumable() method to make the purchase:
final PurchaseParam purchaseParam = PurchaseParam(productDetails: product);
final PurchaseStatus purchaseStatus = await InAppPurchaseConnection.instance.buyNonConsumable(purchaseParam: purchaseParam);

Check the purchaseStatus to see if the purchase was successful.
Note: Before publishing your app, you will need to set up your in-app products in the developer console of the app store where you plan to distribute your app.

Q18. How do you handle form submissions in a Flutter app?

Answer: In a Flutter app, you can handle form submissions by using a Form widget and wrapping the form fields inside it. You can then use a TextFormField for each input field and a RaisedButton for the submit button.

Here’s an example of a simple login form:

Form(
    key: _formKey,
    child: Column(
        children: [
            TextFormField(
                decoration: InputDecoration(labelText: 'Email'),
                validator: (value) {
                    if (value.isEmpty) {
                        return 'Please enter an email';
                    }
                    return null;
                },
                onSaved: (value) => _email = value,
            ),
            TextFormField(
                decoration: InputDecoration(labelText: 'Password'),
                validator: (value) {
                    if (value.isEmpty) {
                        return 'Please enter a password';
                    }
                    return null;
                },
                onSaved: (value) => _password = value,
                obscureText: true,
            ),
            RaisedButton(
                child: Text('Submit'),
                onPressed: _submitForm,
            )
        ],
    ),
)

void _submitForm() {
    if (_formKey.currentState.validate()) {
        _formKey.currentState.save();
        // Perform login
    }
}

In this example, the Form widget has a key property set to _formKey, which is a GlobalKey. This allows you to access the form’s state and validate or save the form fields. The TextFormField widgets have validator and onSaved properties, which are used to validate the input and save the values, respectively. The RaisedButton widget has an onPressed property set to _submitForm, which is a function that is called when the button is pressed. This function checks if the form is valid and, if it is, saves the form fields and performs the login.

Q19. How would you implement a map view in a Flutter app?

Answer: To implement a map view in a Flutter app, you can use the google_maps_flutter package. Here is an example of how to use it:

First, add the package to your pubspec.yaml file:

dependencies:
  google_maps_flutter: ^0.7.0

Next, you will need to add your Google Maps API key to your AndroidManifest.xml and Info.plist files. You can obtain an API key from the Google Cloud Console.

In your Flutter app, import the package:

import 'package:google_maps_flutter/google_maps_flutter.dart';
In your widget tree, add a GoogleMap widget and set the initialCameraPosition property to specify the starting location and zoom level of the map:
Copy code
GoogleMap(
  initialCameraPosition: CameraPosition(
    target: LatLng(37.4219999,-122.0840575),
    zoom: 12,
  ),
)

To add markers to the map, you can use the Marker widget and add it to the GoogleMap widget’s markers property:

GoogleMap(
  markers: Set<Marker>.of(
    [
      Marker(
        markerId: MarkerId('marker_1'),
        position: LatLng(37.4219999,-122.0840575),
        infoWindow: InfoWindow(
          title: 'Marker 1',
          snippet: 'This is marker 1',
        ),
        icon: BitmapDescriptor.defaultMarker,
      ),
    ],
  ),
)

Finally, you can customize the appearance of the map using the GoogleMap widget’s properties, such as mapType, indoorViewEnabled, and trafficEnabled, among others.

Q20. How would you handle user authentication in a Flutter app?

Answer: There are a number of ways to handle user authentication in a Flutter app, but a common approach is to use Firebase Authentication. Here’s an example of how to use Firebase Authentication in a Flutter app:

First, add the following dependencies to your pubspec.yaml file:

dependencies:
  firebase_auth: ^0.18.4+2
  google_sign_in: ^4.5.1

Then, in your app’s main dart file, import the following packages:

import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';

You can use the GoogleSignIn class to handle the Google Sign In process. In this example, you can use GoogleSignInAccount to get user’s account detail and GoogleSignInAuthentication to get user’s auth detail.

final GoogleSignIn _googleSignIn = GoogleSignIn();
final FirebaseAuth _auth = FirebaseAuth.instance;

Future<FirebaseUser> _handleSignIn() async {
  final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
  final GoogleSignInAuthentication googleAuth = await googleUser.authentication;

  final AuthCredential credential = GoogleAuthProvider.getCredential(
    accessToken: googleAuth.accessToken,
    idToken: googleAuth.idToken,
  );

  final FirebaseUser user = (await _auth.signInWithCredential(credential)).user;
  print("signed in " + user.displayName);
  return user;
}

Then, you can call the _handleSignIn() function when the user taps the “Sign In with Google” button.

This is a simple example of how to handle user authentication using Firebase Authentication and Google Sign In in a Flutter app. Keep in mind that this example only covers the basic setup and you may need to implement additional features like handling errors, logging out, etc.

Conclusion:

Overall, the key to success in a Flutter interview is to have a solid understanding of the framework’s core concepts, as well as experience building real-world apps. By studying the questions and code examples in this guide, you’ll be well on your way to impressing potential employers and landing your dream job as a Flutter developer. Be sure to practice your skills and continue to learn and stay up-to-date with the latest developments in the Flutter ecosystem, and you’ll be sure to succeed in your next interview.

If you have any queries related to this article, then you can ask in the comment section, we will contact you soon, and Thank you for reading this article.

Follow me to receive more useful content:

Instagram | Twitter | Linkedin | Youtube

Thank you

Suggested Blog Posts

Leave a Reply

Your email address will not be published.