Author: saqibkhan

  • Unified App UI and Business Logic in All Platforms

    Flutter offers a compelling advantage: the ability to create apps with a consistent UI and shared business logic across all platforms. Unlike traditional native apps that demand separate codebases for Android and iOS, Flutter developers can leverage a single codebase for both operating systems.

    This not only streamlines development efforts but also ensures that the user experience remains uniform across cross platform mobile devices. By harnessing Flutter’s capabilities, you can reduce development costs, accelerate time-to-market, and deliver a seamless app experience to your users.

  • Faster Time-to-Market

    One of the most compelling advantages of opting for Flutter development is its intrinsic ability to significantly expedite the time-to-market process. With a plethora of features that intricately facilitate the software development journey, Flutter empowers you to bring your app to the market in record time, all while seamlessly deploying new features and updates to both iOS and Android platforms simultaneously.

    The efficiency bestowed by Flutter’s unified codebase across multiple platforms is a pivotal element in expediting the time-to-market journey. Unlike the conventional approach that demands separate codebases for Android and iOS, Flutter leverages a single codebase to cater to both platforms. This harmonious coexistence of code expedites the development process by eliminating the need for redundant coding efforts, allowing developers to focus on refining the app’s functionalities rather than wrestling with platform-specific complexities.

  • Database Concepts

    A database is an organized collection of data, which supports the storage and manipulation of data and accessed electronically from a computer system. We can organize data into rows, columns, tables, and indexes. It makes data management easy. We can store many things in the database, like name, age, picture, image, file, pdf, etc.

    Flutter provides many packages to work with the database. The most used and popular packages are:

    • sqflite database: It allows to access and manipulate SQLite database.
    • Firebase database: It will enable you to access and manipulate the cloud database.

    SQLite Database

    SQLite is a popular database software library that provides a relational database management system for local/client storage. It is a light-weight and time-tested database engine and contains features like self-contained, server-less, zero-configuration, transactional SQL database engine.

    Flutter SDK does not support SQLite directly. Instead, it provides a plugin sqflite, which performs all operations on the database as similar to the SQLite library. The sqflite provides most of the core functionalities related to the database are as follows:

    • It creates or opens the SQLite database.
    • It can execute SQL statements easily.
    • It also provides an advanced query method to get information from the SQLite database.

    Let us see step by step how we can store and fetch data in the Flutter.

    Step 1: First, create a new project in Android Studio and add the dependencies in pubspec.yaml file.

    1. dependencies:  
    2.   flutter:  
    3.     sdk: flutter  
    4.   sqflite: any  
    5.   path_provider: any  
    • The sqflite package provides classes and functions to interact with the SQLite database.
    • The path_provider package provides functions to define the location of your database on the local system, such as TemporaryDirectory and ApplicationDocumentsDirectory.

    Step 2: Create a model class. In this step, we have to define the data that needs to be stored before creating a table to store information. The following code explains it easily.

    class Book {  
    
      final int id;  
    
      final String title;  
    
      final int price;  
    
      
    
      Book({this.id, this.title, this.price});  
    
    } 

      Step 3: Open the database. Here, we need to open the connection to the database. It requires two steps:

      1. Set the path to the database by using the getDtabasePath() method and combined it with the path package.
      2. Use openDatabase() function to open the database.
      // It allows to open the database and store the reference.  
      
      final Future<Database> database = openDatabase(  
      
        join(await getDatabasesPath(), 'book_database.db'),  
      
      ); 

        Step 4: Create the table. In this step, we have to create a table that stores information about the books. Here, we are going to create a table named books, which contains the id, title, and price of the books. They are represented as three columns in the book table.

        final Future<Database> database = openDatabase(  
        
          join(await getDatabasesPath(), 'book_database.db'),  
        
          // When you create a database, it also needs to create a table to store books.  
        
          onCreate: (db, version) {  
        
            // Run the CREATE TABLE statement.  
        
            return db.execute(  
        
              "CREATE TABLE books(id INTEGER PRIMARY KEY, title TEXT, price INTEGER)",  
        
            );  
        
          },  
        
          // Set the version to perform database upgrades and downgrades.  
        
          version: 1,  
        
        );

        Step 5: Insert a Book into the database. Here, you have to store information on the table about the various books. Inserting a book into the table involves two steps:

        • Convert the Book into a Map
        • Uses insert() method

        The following code explains it more clearly.

        // Update the Book class.  
        
        class Book{  
        
          final int id,  
        
          final String title;  
        
          final int price;  
        
          
        
          Book({this.id, this.title, this.price});  
        
          
        
          // It converts a Book into a Map. The keys correspond to the names of the columns in the database.  
        
          Map<String, dynamic> toMap() {  
        
            return {  
        
              'id': id,  
        
              'title': title,  
        
              'price': price,  
        
            };  
        
          }  
        
        }  
        
          
        
        Future<void> insertBook(Book book) async {  
        
          final Database db = await database;  
        
          await db.insert(  
        
            'books',  
        
            book.toMap(),  
        
            conflictAlgorithm: ConflictAlgorithm.replace,  
        
          );  
        
        }  
        
          
        
        // Create a Book and add it to the books table.  
        
        final b1 = Book(  
        
          id: 0,  
        
          title: 'Let Us C',  
        
          price: 350,  
        
        );  
        
          
        
        await insertBook(b1); 

          Step 6: Retrieve the list of books. Now, we have stored the book into the database, and you can use a query to retrieve a particular book or list of all books. It involves two steps:

          • Run a query that returns List<Map>.
          • Convert the List<Map> into the List<Book>.

          You can see the following code to understand it easily.

          // This method retrieves all the books from the books table.  
          
          Future<List<Book>> books() async {  
          
            final Database db = await database;  
          
            
          
            // Use query for all Books.  
          
            final List<Map<String, dynamic>> maps = await db.query('maps');  
          
            
          
            return List.generate(maps.length, (i) {  
          
              return Book(  
          
                id: maps[i]['id'],  
          
                title: maps[i]['title'],  
          
                price: maps[i]['price'],  
          
              );  
          
            });  
          
          }  
          
            
          
          // It prints all the books.  
          
          print(await books());

          Step 7: Update a Book in the database. You can use an update() method to update the book that you want. It involves two steps:

          • Convert Book into the Map.
          • Then, use where clause to update the book.

          You can see the following code to understand it.

          Future<void> updateBook(Book book) async {  
          
            final db = await database;  
          
            
          
            // Update the given Book.  
          
            await db.update(  
          
              'books',  
          
              book.toMap(),  
          
              // It ensure the matching id of a Book.  
          
              where: "id = ?",  
          
              whereArgs: [book.id],  
          
            );  
          
          }  
          
            
          
          // Update b1 price.  
          
          await updateBook(Book(  
          
            id: 0,  
          
            title: 'Let Us C',  
          
            price: 420,  
          
          ));  
          
            
          
          // Print the updated results.  
          
          print(await books());

          Step 8: Delete a Book from the database. You can use the delete() method to delete the database. For this, you need to make a function that takes an id and delete the database of the matching id.

          Future<void> deleteBook(int id) async {  
          
            final db = await database;  
          
            
          
            // This function removes books from the database.  
          
            await db.delete(  
          
              'books',  
          
              where: "id = ?",  
          
              whereArgs: [id],  
          
            );  
          
          }  

            Let us see the complete code to understand how we can create a database file with sqflite plugin. For this, create a new Flutter project and the sqflite and path package into the pubspec.yaml file. Next, create a new file into the lib folder and insert the following code in this file. Now, connect the database with your UI and run the code.

            import 'dart:async';  
            
              
            
            import 'packprice:path/path.dart';  
            
            import 'packprice:sqflite/sqflite.dart';  
            
              
            
            void main() async {  
            
              final database = openDatabase(  
            
                join(await getDatabasesPath(), 'book_database.db'),  
            
                onCreate: (db, version) {  
            
                  return db.execute(  
            
                    "CREATE TABLE books(id INTEGER PRIMARY KEY, title TEXT, price INTEGER)",  
            
                  );  
            
                },  
            
                version: 1,  
            
              );  
            
              
            
              Future<void> insertBook(Book book) async {  
            
                // Get a reference to the database.  
            
                final Database db = await database;  
            
              
            
                await db.insert(  
            
                  'books',  
            
                  book.toMap(),  
            
                  conflictAlgorithm: ConflictAlgorithm.replace,  
            
                );  
            
              }  
            
              
            
              Future<List<Book>> books() async {  
            
                final Database db = await database;  
            
              
            
                final List<Map<String, dynamic>> maps = await db.query('books');  
            
              
            
                return List.generate(maps.length, (i) {  
            
                  return Book(  
            
                    id: maps[i]['id'],  
            
                    title: maps[i]['title'],  
            
                    price: maps[i]['price'],  
            
                  );  
            
                });  
            
              }  
            
              
            
              Future<void> updateBook(Book book) async {  
            
                final db = await database;  
            
                await db.update(  
            
                  'books',  
            
                  book.toMap(),  
            
                  where: "id = ?",  
            
                  whereArgs: [book.id],  
            
                );  
            
              }  
            
              
            
              Future<void> deleteBook(int id) async {  
            
                final db = await database;  
            
                await db.delete(  
            
                  'books',  
            
                  where: "id = ?",  
            
                  whereArgs: [id],  
            
                );  
            
              }  
            
              
            
              var b1 = Book(  
            
                id: 0,  
            
                title: 'Let Us C',  
            
                price: 300,  
            
              );  
            
              
            
              await insertBook(b1);  
            
              
            
              print(await books());  
            
              
            
              b1 = Book(  
            
                id: b1.id,  
            
                title: b1.title,  
            
                price: b1.price,  
            
              );  
            
              await updateBook(b1);  
            
              
            
              print(await books());  
            
              
            
              await deleteBook(b1.id);  
            
              
            
              print(await books());  
            
            }  
            
              
            
            class Book {  
            
              final int id;  
            
              final String title;  
            
              final int price;  
            
              
            
              Book({this.id, this.title, this.price});  
            
              
            
              Map<String, dynamic> toMap() {  
            
                return {  
            
                  'id': id,  
            
                  'title': title,  
            
                  'price': price,  
            
                };  
            
              }  
            
              @override  
            
              String toString() {  
            
                return 'Book{id: $id, title: $title, price: $price}';  
            
              }  
            
            } 
            1. Open source and an engaged community

              As an open-source platform, Flutter is free to use and has a growing community contributing to its outstanding documentation and assisting with issues that developers may encounter. There are also many YouTube videos available for those who want to start learning Flutter or improve their skills in this Google’s mobile UI framework.

            2. Internationalization and accessibility

              Internationalization, or preparing different language and region versions of your app, usually happens after the app itself is created and can produce multiple discrepancies. Flutter provides tools that make this process a breeze and incorporate it directly into development. Flutter also supports accessibility, enabling large fonts, screen readers, and enhanced contrast, all of this automated from within the platform.

            3. Going beyond mobile

              It’s possible to develop Flutter products that work on the web, desktop, and even TV, which many developers are already doing. These features are still in different stages of advancement, but Google definitely has the capacity to create a stable release. Considering how important IoT is for the company, they will most likely keep developing Flutter in this direction.

            4. High performance

              Flutter applications perform at a level comparable with native mobile apps and are winning over other cross-platform technologies. That’s mostly because Flutter is the only mobile SDK that doesn’t use a bridge (JavaScript or webview) for communication between the app and the platform. As a result, you get a faster-starting app with beautiful, fast animations and fewer performance problems.

            5. Widgets and compatibility

              Widgets are the building blocks on which the whole app is based. There are ready-made as well as customizable ones – everything in Flutter can be built from widgets. Since widgets are part of the app and not the specific platform, the end product will most likely have fewer compatibility issues on different platforms and OS versions.

            6. REST API

              In this section, we are going to learn how we can access the REST API in the Flutter app. Today, most of the apps use remote data using APIs. So, this section will be the important part for those developers who want to make their carrier in Flutter.

              Flutter provides http package to use http resources. The http package uses await and async features and provides many high-level methods such as read, get, post, put, head, and delete methods for sending and receiving data from remote locations. These methods simplify the development of REST-based mobile applications.

              The detail explanation of the core methods of the http package are as follows:

              Read: This method is used to read or retrieve the representation of resources. It requests the specified url by using the get method and returns the response as Future<String>.

              Get: This method requests the specified url from the get method and returns a response as Future<response>. Here, the response is a class, which holds the response information.

              Post: This method is used to submit the data to the specified resources. It requests the specified url by posting the given data and return a response as Future<response>.

              Put: This method is utilized for update capabilities. It updates all the current representation of the target resource with the request payloads. This method request the specified url and returns a response as Future<response>.

              Head: It is similar to the Get method, but without the response body.

              Delete: This method is used to remove all the specified resources.

              The http package also provides a standard http client class that supports the persistent connection. This class is useful when a lot of requests to be made on a particular server. It should be closed properly using the close() method. Otherwise, it works as an http class. The following code explains it more clearly.

              var client = new http.Client();   
              
              try {   
              
                 print(await client.get('https://www.javatpoint.com/'));   
              
              }   
              
              finally {   
              
                 client.close();   
              
              }  

                To fetch data from the internet, you need to follow these necessary steps:

                Step 1: Install the latest http package and add it to the project.

                To install the http package, open the pubspec.yaml file in your project folder and add http package in the dependency section. You can get the latest http package here and add it like:

                dependencies:  
                
                  http: <latest_version> 

                  You can import the http package as:

                  import 'package:http/http.dart' as http;  

                  Step 2: Next, make a network request by using the http package.

                  In this step, you need to make a network request by using the http.get() method

                  Future<http.Response> fetchPost() {  
                  
                    return http.get('https://jsonplaceholder.typicode.com/posts/1');  
                  
                  } 

                    In the above code, the Future is a class that contains an object. The object represents a potential value or error.

                    Step 3: Now, convert the response getting from network request into a custom Dart object.

                    First, you need to create a Post class. The Post class received data from the network request and includes a factory constructor, which creates Post from JSON. You can create a Post class as below:

                    class Post {  
                    
                      final int userId;  
                    
                      final int id;  
                    
                      final String title;  
                    
                      final String body;  
                    
                      
                    
                      Post({this.userId, this.id, this.title, this. description});  
                    
                      
                    
                      factory Post.fromJson(Map<String, dynamic> json) {  
                    
                        return Post(  
                    
                          userId: json['userId'],  
                    
                          id: json['id'],  
                    
                          title: json['title'],  
                    
                          description: json['description'],  
                    
                        );  
                    
                      }  
                    
                    }  

                      Now, you have to convert the http.response to a Post. The following code updates the fetchPost() function for returning a Future<Post>.

                      Future<Post> fetchPost() async {  
                      
                        final response = await http.get( Give the link of JSON file');  
                      
                        
                      
                        if (response.statusCode == 200) {  
                      
                          // If the server returns an OK response, then parse the JSON.  
                      
                          return Post.fromJson(json.decode(response.body));  
                      
                        } else {  
                      
                          // If the response was umexpected, throw an error.  
                      
                          throw Exception('Failed to load post');  
                      
                        }  
                      
                      } 

                        Step 4: Now, fetch the data with Flutter. You can call the fetch method in the initState(). The following code explains how you can fetch the data.

                        class _MyAppState extends State<MyApp> {  
                        
                          Future<Post> post;  
                        
                          
                        
                          @override  
                        
                          void initState() {  
                        
                            super.initState();  
                        
                            post = fetchPost();  
                        
                          }  

                          Step 5: Finally, display the data. You can display the data by using the FutureBuilder widget. This widget can work easily with async data sources.

                          FutureBuilder<Post>(  
                          
                            future: post,  
                          
                            builder: (context, abc) {  
                          
                              if (abc.hasData) {  
                          
                                return Text(abc.data.title);  
                          
                              } else if (abc.hasError) {  
                          
                                return Text("${abc.error}");  
                          
                              }  
                          
                            
                          
                              // By default, it show a loading spinner.  
                          
                              return CircularProgressIndicator();  
                          
                            },  
                          
                          );

                          Let us see the complete code to understand how Flutter works with REST API to fetch data from the network. You can learn more in detail from here.

                          import 'dart:async';  
                          
                          import 'dart:convert';  
                          
                            
                          
                          import 'package:flutter/material.dart';  
                          
                          import 'package:http/http.dart' as http;  
                          
                            
                          
                          void main() => runApp(MyApp());  
                          
                            
                          
                          class MyApp extends StatefulWidget {  
                          
                            MyApp({Key key}) : super(key: key);  
                          
                            
                          
                            @override  
                          
                            _MyAppState createState() => _MyAppState();  
                          
                          }  
                          
                            
                          
                          class _MyAppState extends State<MyApp> {  
                          
                          Future<Post> post;  
                          
                            
                          
                            @override  
                          
                            void initState() {  
                          
                              super.initState();  
                          
                              post = fetchPost();  
                          
                            }  
                          
                            
                          
                            @override  
                          
                            Widget build(BuildContext context) {  
                          
                              return MaterialApp(  
                          
                                title: 'Flutter REST API Example',  
                          
                                theme: ThemeData(  
                          
                                  primarySwatch: Colors.green,  
                          
                                ),  
                          
                                home: Scaffold(  
                          
                                  appBar: AppBar(  
                          
                                    title: Text('Flutter REST API Example'),  
                          
                                  ),  
                          
                                  body: Center(  
                          
                                    child: FutureBuilder<Post>(  
                          
                                      future: post,  
                          
                                      builder: (context, abc) {  
                          
                                        if (abc.hasData) {  
                          
                                          return Text(abc.data.title);  
                          
                                        } else if (abc.hasError) {  
                          
                                          return Text("${abc.error}");  
                          
                                        }  
                          
                            
                          
                                        // By default, it show a loading spinner.  
                          
                                        return CircularProgressIndicator();  
                          
                                      },  
                          
                                    ),  
                          
                                  ),  
                          
                                ),  
                          
                              );  
                          
                            }  
                          
                          }  
                          
                            
                          
                          Future<Post> fetchPost() async {  
                          
                            final response = await http.get('Give your JSON file web link.');  
                          
                            
                          
                            if (response.statusCode == 200) {  
                          
                              // If the call to the server was successful (returns OK), parse the JSON.  
                          
                              return Post.fromJson(json.decode(response.body));  
                          
                            } else {  
                          
                              // If that call was not successful (response was unexpected), it throw an error.  
                          
                              throw Exception('Failed to load post');  
                          
                            }  
                          
                          }  
                          
                            
                          
                          class Post {  
                          
                            final int userId;  
                          
                            final int id;  
                          
                            final String title;  
                          
                            final String description;  
                          
                            
                          
                            Post({this.userId, this.id, this.title, this. description});  
                          
                            
                          
                            factory Post.fromJson(Map<String, dynamic> json) {  
                          
                              return Post(  
                          
                                userId: json['userId'],  
                          
                                id: json['id'],  
                          
                                title: json['title'],  
                          
                                description: json[' description'],  
                          
                              );  
                          
                            }  
                          
                          }

                          The JSON file is shown below.

                          [   
                          
                             {   
                          
                                "userId": 01,   
                          
                                "id": 1,   
                          
                                "title": "iPhone",   
                          
                                "description": "iPhone is the very stylist phone ever"  
                          
                             },   
                          
                             {   
                          
                                "userId": 02,   
                          
                                "id": 2,   
                          
                                "title": "Pixel",   
                          
                                "description": "Pixel is the most feature phone ever"  
                          
                             },   
                          
                             {   
                          
                                "userId": 03,   
                          
                                "id": 3,   
                          
                                "title": "Laptop",   
                          
                                "description": "Laptop is most popular development tool"  
                          
                             },   
                          
                             {   
                          
                                "userId": 04,   
                          
                                "id": 4,   
                          
                                "title": "Tablet",   
                          
                                "description": "Tablet is the most useful device used for meeting"   
                          
                             }  
                          
                          ] 
                          1. Efficient development process

                            As a cross-platform technology, Flutter enables developing an app for both operating systems using the same codebase. But that’s not the only reason why using Flutter makes the development process faster and more efficient. It also includes hot restart and a well-regarded “hot reload” function, which allows you to see updates in real time without restarting the app.

                            This significantly speeds up the development process. React Native and Xamarin have similar functions, but they are slower. With these features, Flutter lets you save time and resources.