Flutter: A Developer's Guide to Building High-Quality Apps

Learn how to build beautiful and feature-rich mobile apps using Flutter, from the basics to advanced concepts.

Flutter: A Developer's Guide to Building High-Quality Apps

Flutter is a popular open-source mobile application development framework enabling developers to build beautiful, high-performance, natively compiled mobile applications for Android and iOS platforms using a single codebase. In this blog, we will guide you through the process of learning Flutter development from scratch.

Prerequisites:

  1. Before you can start building Flutter apps, you must set up your development environment. This includes installing the Flutter SDK, Android Studio, and VS Code, XCode, and Cocoapods you might need. If you haven't already installed Flutter, follow the instructions on the official Flutter website to download and install it on your computer.

  2. Flutter uses Dart as its programming language. Dart is a modern, object-oriented programming language with a syntax that is easy to learn and understand. You should spend some time learning Dart programming, including its syntax, data types, variables, functions, and control structures.

Dart Basics:

Here's a quick reference of important things to keep in mind when using Dart for Flutter:

Data Structures and Variables:

// Importing core libraries
import 'dart:math';
// Importing libraries from external packages
import 'package:test/test.dart';
// Importing files
import 'path/to/my_other_file.dart';

void main(){
    // This is a normal, one-line comment.

    /// This is a documentation comment, used to document libraries,
    /// classes, and their members. Tools like IDEs and dartdoc treat
    /// doc comments specially.

    int x = 2;
    var p = 5;
    dynamic z = 8;
    z = "cool";
    final email = "temid@gmail.com"; 
    const qty = 5;

    var multilist = [];
    multilist.add([1,2]);
    multilist.add([3,6,1,4,6,9]);
    for (List<int> i in multilist) {
        print ("list: $i");
        i.sort((x,y) {
            return x>y ? x : y;
        });
        print("sorted list: ${i.toString()}");
    }


   var person = {};
   person["name"] = "Khandoker Kafi Anan";
   person["age"] = 22;
   person["socials"] = {
     "facebook": "https://facebook.com/khandoker.anan",
     "website" : "https://khandokeranan.com",
     "linkedin": "httpsL//linkedin.com/in/khandokeranan"
   };
   person["favorite_numbers"] = [6,5,11,28,101,7,3];

   person.forEach( (key,val) {
     print ("$key : $val");
   });

}

Class, Inheritance, mixin, and Polymorphism:

class Analytics {
    int totalViewsCount = 0;
    int blogId = 0;
    Analytics (int blogId, int totalViewsCount) {
      this.blogId = blogId;
      this.totalViewsCount = totalViewsCount;
    }
    void increaseView () {
      totalViewsCount++;
    }
}

class Audio {
    void playSound (String filename) {
        print ("Playing $filename");
    }
}

class BlogWriter extends Analytics with Audio{
    String? title, description, author;
    BlogWriter( super.blogId, super.totalViewsCount, { required this.title, this.description, required this.author});

    void showDetails () {
        description ??= "No description found";
        print ("Title: $title\nDescription: $description\nAuthor: $author\nBlog ID: $blogId\nTotal Views: $totalViewsCount");
    }

    @override 
    void increaseView () {
      totalViewsCount+=2;
    }
}

void main () {

    BlogWriter bw = BlogWriter(11, 2011, title: "Anan's Sight", description: "This is a blog", author: "Khandoker Anan");
    bw.increaseView ();
    bw.showDetails();
    bw.playSound("C:/app/anan.mp3");

}

Optional Function Passing in a Function:

int maxVal (List<int> v) {
    int maxv = -999999999999;
    for (int i=0; i<v.length; i++) {
        maxv = (maxv < v[i]) ? v[i] : maxv;
    }
    return maxv;
}
void deleteMaxVal(var v, {Function max = maxVal}) {
  var maxValue = max(v);
  bool check = v is List && v.isNotEmpty && maxValue.runtimeType.toString() == v[0].runtimeType.toString();
  if (check) {
    v.remove(maxValue); 
    print (v);
  }

}
void main () {
  var v = [4,3,6,1,3,11,33,55,1,21];
  print (maxVal (v));
  deleteMaxVal(v, max: maxVal);
}

Flutter Project Creation and Source Control:

HOW TO CREATE A FLUTTER PROJECT

To create a flutter project, we need to run this command on the specific folder's terminal/CMD:

flutter create --org com.khandokeranan -i swift -a kotlin testdesign

"com.khandokeranan" represents the organization's name and type, and "-i swift" uses for using swift for iOS development, and "-a kotlin" uses for using kotlin for android development.

FLUTTER DEFAULT PROJECT STRUCTURE

using the flutter create command, it generates a default project structure with several directories and files. Here's an overview of the main directories and files in a typical Flutter project:

  1. android: This directory contains the Android-specific configuration files, such as the Gradle build scripts, AndroidManifest.xml, and other resources required for building and running the Flutter app on Android.

  2. ios: This directory contains the iOS-specific configuration files, such as the Xcode project, Info.plist, and other resources required for building and running the Flutter app on iOS.

  3. lib: This directory is the heart of your Flutter app, and it contains the Dart source code for your app. It's where we'll write our app's main logic and UI code using Flutter widgets.

  4. test: This directory is used for writing tests for your Flutter app. It can contain unit tests, integration tests, and widget tests to ensure the quality and correctness of your app.

  5. assets: This directory is used for storing static assets, such as images, fonts, and other files, that are bundled with your app. You can access these assets in your Flutter app using the AssetBundle class.

  6. lib/main.dart: This is the entry point of your Flutter app. It contains the main() function, which is the starting point of your app's execution.

  7. pubspec.yaml: This is the configuration file for our Flutter app, written in YAML format. It contains your app's dependencies, assets, and other settings, such as the app name, version, and description.

  8. pubspec.lock: Flutter automatically generates this file and contains the locked versions of the dependencies used in your app, ensuring that the same dependencies are used across different builds.

  9. build: This directory is automatically generated by Flutter, and it contains the compiled output of your app, including the APK (Android) and IPA (iOS) files, as well as intermediate build artifacts.

ACTIVATING GITHUB REPOSITORY WITH THE PROJECT INSIDE VS CODE

Make sure Git is installed. VS Code will use your machine's Git installation (at least version 2.0.0), so you need to install Git first before you get these features to publish the project directly to GitHub. By following these two steps to publish the repository to a public or private remote repository to GitHub without using commands, we can commit to the project, open new branches for production, development, android-specific, etc, manage branches and commits and collaborate with other developers.

To know more about it, click the image for more references.

The First Hello World Flutter App from Scratch:

The git repo: https://github.com/anwholesquare/flutter-testdesign/tree/13d9c28909d9f2a30216952273726d2e1b38461e

import 'package:flutter/material.dart';
void main () {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.blue
      ),
      home: const Material (
        child: Center(
          child: Text("Hello World", 
            style: TextStyle(
              fontSize: 24,
              fontWeight: FontWeight.bold
            ),
          ),
        ),
      )

    );
  }
}

The rest of the blog is to be continued.