2
Creating a Hello World App

WHAT YOU WILL LEARN IN THIS CHAPTER

  • How to create a new Flutter mobile app
  • How to refresh the running app with hot reload
  • How to style the app with themes
  • When to use a stateless or stateful widget
  • How to add external packages

A great way to learn a new development language is to write a basic app. In programming, Hello World is the most basic program to write. It simply displays the words Hello World on the screen. In this chapter, you'll learn the main steps of how to develop this basic program as a Flutter app. Do not worry about understanding the code yet; I'll walk you through it step‐by‐step later in this book.

Writing this minimal example helps you learn the basic structure of a Flutter app, how to run the app on the iOS simulator and the Android emulator, and how to make changes to the code.

SETTING UP THE PROJECT

The initial project setup for each app is the same. I'm using Android Studio to create the sample apps in this book, but you can choose a different editor such as IntelliJ or Visual Studio Code. An overview of the process in Android Studio is as follows: you create a new Flutter project, select the Flutter application as the project type (template), and enter the project name. The Flutter software development kit (SDK) then creates the project for you, including creating a project directory with the same name as the project name. Within the project directory, the lib folder contains the main.dart file with the source code (in other words, project_name/lib/main.dart). You'll also have an android folder for the Android app, the ios folder for the iOS app, and a test folder for unit testing.

In this chapter, the lib folder and the main.dart file are your primary focus. In Chapter 4, “Creating a Starter Project Template,” you will learn how to create a Flutter starter project and how to structure code into separate files.

By default, the Flutter app uses Material Components widgets based on Material Design. Material Design is a system of best‐practice guidelines for user interface design. The components in a Flutter project include visual, behavioral, and motion widgets. Flutter projects also include unit testing for widgets, which are files that contain individual code to test whether the logic performs as designed.

Flutter applications are built with the Dart programming language, and you will learn the basics of Dart in Chapter 3, “Learning Dart Basics.”

USING HOT RELOAD

Flutter's hot reload helps you see code and user interface changes immediately while retaining state to an app running the Dart virtual machine. In other words, every time you make code changes, you don't need to reload the app, because the current page shows the changes immediately. This is an incredible time‐saving feature for any developer.

In Flutter, the State class stores mutable (changeable) data. For example, the app starts with the counter value set to zero, but each time you tap the + button, the counter value increases by one. When the + button is tapped three times, the counter value shows a value of three. The counter value is mutable, so it can change over time. By using hot reload, you can make code logic changes, and the app's counter state (value) does not reset to zero but instead retains the current value of three.

USING THEMES TO STYLE YOUR APP

The theme widgets are a great way to style and define global colors and font styles for your app. There are two ways to use theme widgets—to style the look and feel globally or to style just a portion of the app. For instance, you can use themes to style the color brightness (light text on a dark background or vice versa); the primary and accent colors; the canvas color; and the color of app bars, cards, dividers, selected and unselected options, buttons, hints, errors, text, icons, and so on. The beauty of Flutter is that most items are widgets, and just about everything is customizable. In fact, customizing the ThemeData class allows you to change the color and typography of widgets. (You'll learn more about widgets in detail in Chapter 5, “Understanding the Widget Tree,” and Chapter 6, “Using Common Widgets.”)

Using a Global App Theme

Let's take the new ch2_my_counter app and modify the primary color. The current color is blue, so let's change it to light green. Add a new line below the primarySwatch and add code to change the background color (canvasColor) to lightGreen.

primarySwatch: Colors.blue,
// Change it to
primarySwatch: Colors.lightGreen,
canvasColor: Colors.lightGreen.shade100,

Save by pressing image (in Windows image). Hot reload is invoked, so the app bar and the canvas are now both a light shade of green.

To show a little Flutter awesomeness, add a platform property of TargetPlatform.iOS after the canvasColor property, and run the app from the Android emulator. Suddenly, the iOS traits are running on Android. The app bar's title is not left aligned but changed to the center, which is the customary iOS style (Figure 2.1).

Screenshot of iOS traits running in Android.

FIGURE 2.1: iOS traits running in Android

primarySwatch: Colors.blue,
// Change it to
primarySwatch: Colors.lightGreen,
canvasColor: Colors.lightGreen.shade100,
platform: TargetPlatform.iOS

This can be done in reverse by using TargetPlatform. Specifically, to show Android traits on iOS, change the platform property to TargetPlatform.android and run the app from the iOS simulator. The app bar's title is not center aligned but has changed to be left aligned, which is the customary Android style (Figure 2.2). Once navigation with multiple pages is implemented, this will be even more apparent. In iOS when navigating to a new page, you usually slide the next page from the right side of the screen towards the left. In Android when navigating to a new page, you usually slide the next page from bottom to top. TargetPlatform has three choices: Android, Fuchsia (the operating system under development from Google), and iOS.

Screenshot of Android traits running in iOS.

FIGURE 2.2: Android traits running in iOS

primarySwatch: Colors.blue,
// Change it to
primarySwatch: Colors.lightGreen,
canvasColor: Colors.lightGreen.shade100,
platform: TargetPlatform.android

Here's another example of using a global app theme: if you have a red debug banner on the upper right of the emulator, you can turn it off with the following code. Google intended to let developers know that the app performance is not in release mode. Flutter builds a debug version of the app, and performance is slower. Using release (device only) mode, it creates an app with speed optimization. Add the debugShowCheckedModeBanner property and set the value to false, and the red debug banner is removed. Turning off the red debug banner is for aesthetic purposes only; you are still running a debug version of the app.

return new MaterialApp(
 debugShowCheckedModeBanner: false,
 title: 'My Counter',
 theme: new ThemeData(

Using a Theme for Part of an App

To override the app‐wide theme, you can wrap widgets in a Theme widget. This method will completely override the app ThemeData instance without inheriting any styles.

In the previous section, you changed primarySwatch and canvasColor to lightGreen, which affected all widgets in the app. What if you want only one widget on a page to have a different color scheme and the rest of the widgets to use the default global app theme? You override the default theme with a Theme widget that uses the data property to customize ThemeData (such as cardColor, primaryColor, and canvasColor), and the child widget uses the data property to customize the colors.

body: Center(
 child: Theme(
  // Unique theme with ThemeData - Overwrite  data: ThemeData(
   cardColor: Colors.deepOrange,
  ),
  child: Card(
   child: Text('Unique ThemeData'),
  ),
 ),
),

I recommend extending the app parent theme, changing only the properties needed and inheriting the rest. Use the copyWith method to create a copy of the app parent theme and replace only the properties that you need to change. Breaking it down, Theme.of(context).copyWith() extends the parent Theme, and you can override the properties needed inside copyWith(cardColor: Colors.deepOrange).

body: Center(
 child: Theme(
  // copyWith Theme - Inherit (Extended)
  data: Theme.of(context).copyWith(cardColor: Colors.deepOrange),
  child: Card(
   child: Text('copyWith Theme'),
  ),
 ),
),

The following sample code shows how to change the default Card color to deepOrange with Theme overwritten (ThemeData()) and extended (Theme.of().copyWith()) to produce the same result. The two Theme widgets are wrapped inside a Column widget to align them vertically. At this point, do not worry about the Column widget, as it's covered in Chapter 6.

body: Column(
 children: <Widget>[
  Theme(
   // Unique theme with ThemeData - Overwrite
   data: ThemeData(
    cardColor: Colors.deepOrange,
   ),
   child: Card(
    child: Text('Unique ThemeData'),
   ),
  ),
  Theme(
   // copyWith Theme - Inherit (Extended)
   data: Theme.of(context).copyWith(cardColor: Colors.deepOrange),
   child: Card(
    child: Text('copyWith Theme'),
   ),
  ),
 ],
),

UNDERSTANDING STATELESS AND STATEFUL WIDGETS

Flutter widgets are the building blocks for designing the user interface (UI). Widgets are built using a modern react‐style framework. The UI is created by nesting widgets together into a widget tree.

Flutter's react‐style framework means it observes when the state of a widget changes and then compares it to the previous state to determine the least number of changes to make. Flutter manages the relationship between the state and the UI and rebuilds only those widgets when the state changes.

In this section, you'll compare stateless and stateful widgets and learn how to implement each class and most importantly which one to use depending on the requirement. In later chapters, you'll create apps for each scenario. The appropriate class is extended (making it a subclass) by using the keyword extends followed by either StatelessWidget or StatefulWidget.

StatelessWidget is used when data does not change, and it relies on the initial information. It's a widget without state, and the values are final. Some examples are Text, Button, Icon, and Image.

class Instructions extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
  return Text('When using a StatelessWidget…');
 }
}

StatefulWidget is used when data changes. It's a widget with state that might change over time, requiring two classes. For changes to propagate to the UI, making a call to the setState() method is necessary.

  • StatefulWidget class—This creates an instance of the State class.
  • State class—This is for data that can be read synchronously when the widget is built and might change over time.
  • setState()—From within the State class, you make a call to the setState() method to refresh changed data, telling the framework that the widget should redraw because the state has changed. For all the variables that need changes, modify the values in setState(() { _myValue += 50.0;}). Any variable values modified outside the setState() method will not refresh the UI. Therefore, it is best to place calculations that do not need state changes outside the setState() method.

Consider the example of a page that shows your maximum bid on a product. Every time the Increase Bid button is tapped, your bid increases by $50. You begin by creating a MaximumBid class that extends the StatefulWidget class. Create a _MaximumBidState class that extends the state of the MaximumBid class.

In the _MaximumBidState class, you declare a variable named _maxBid. The _increaseMyMaxBid() method calls the setState() method, which increments the _maxBid value by $50. The UI consists of a Text widget that shows the 'My Maximum Bid: $_maxBid' value and a FlatButton with an onPressed property that calls the _increaseMyMaxBid() method. The _increaseMyMaxBid() method executes the setState() method, which adds $50 to the _maxBid variable, and the Text widget amount is redrawn.

class MaximumBid extends StatefulWidget {
 @override
 _MaximumBidState createState() => _MaximumBidState();
}

class _MaximumBidState extends State<MaximumBid> {
 double _maxBid = 0.0;

 void _increaseMyMaxBid() {
  setState(() {
   // Add $50 to my current bid
   _maxBid += 50.0;
  });
 }

 @override
 Widget build(BuildContext context) {
  return Column(
   children: <Widget>[
    Text('My Maximum Bid: $_maxBid'),
    FlatButton.icon(
      onPressed: () => _increaseMyMaxBid(),
      icon: Icon(Icons.add_circle),
      label: Text('Increse Bid'),
    ),
   ],
  );
 }
}

USING EXTERNAL PACKAGES

Sometimes it's not worth building a widget from scratch. Flutter supports third‐party packages for the Flutter and Dart ecosystems. Packages contain the source code logic and are easily shared. There are two types of packages, Dart and plugin.

  • Dart packages are written in Dart and may contain Flutter‐specific dependencies.
  • Plugin packages are written in Dart (with the Dart code exposing the API) but are combined with platform‐specific code implementations for Android (Java or Kotlin) and/or iOS (Objective‐C or Swift). Most plugin packages aim to support both Android and iOS.

Let's say you are looking to add functionality to your app such as showing some charts, accessing a device's GPS locations, playing background audio, or accessing a database like Firebase. There are packages for all that.

Searching for Packages

In the app, say you need to store the user preferences on both iOS and Android and want to find a package to do that for you.

  1. Start your web browser and navigate to https://pub.dartlang.org/flutter. Packages are published at this location often by other developers and Google.
  2. Click the Search Flutter Packages search bar. Enter shared preferences, and the results will be sorted by relevance.
  3. Click the link for the shared_preferences package. (The direct link is https://pub.dartlang.org/packages/shared_preferences.)
  4. Details on how to install and use the shared_preferences package are available at this location. The Flutter team authors this particular package. Click the Installing tab for detailed instructions. Each package has instructions on how to install and use it. Most of the packages' installation is similar, but they differ on how to use and implement the code. The instructions are located on the home page of each package.

Using Packages

Each package has its unique way of being implemented. It's always good to read the documentation. For the shared_preferences package, you need to add a few lines to implement it. Please remember the main point here is not how to use this package but how to add external packages to your app in general.

SUMMARY

In this chapter, you learned how to create your first app and use hot reload to view changes instantaneously. You also saw how to use themes to style apps, when to use stateless and stateful widgets, and how to add external packages to save yourself from reinventing the wheel. You now have a general understanding of the main ideas behind Flutter app development. Do not worry about understanding the actual code yet. You'll learn all about it throughout the book.

In the next chapter, you'll learn the basics of the Dart language that is used to create Flutter apps.

image WHAT YOU LEARNED IN THIS CHAPTER

TOPIC KEY CONCEPTS
Creating a Flutter app You can now code a basic app and lay out widgets.
Using hot reload Hot reload shows code changes immediately in a running app while maintaining state.
Applying a theme Themes set the style and colors throughout an app.
Using external packages External packages search for and install third‐party packages to add functionalities such as GPS, charting, and more.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset