This article aims to introduce Flutter beginners in an easy to understand way. In addition to the Flutter code, the basic knowledge of Flutter syntax, principles, and features will also be introduced. I believe this article will help you learn and understand Flutter.
Introduction to Cross-platform Technology
Let’s take a look at some of the current cross-platform solutions. From the perspective of front-end rendering, we can roughly divide them into the following solutions.
The WebView rendering
This approach makes sense, as many projects are now embedded in H5 pages. Is to use JavaScript and other front-end technology for development, in the client with WebView to render. This scheme is currently used in wechat mini program.
Its advantages are obvious, using mature front-end technology for development, low learning cost, high development efficiency, and support for dynamic release of code.
But the disadvantages are also obvious, in the performance experience, and there is a big gap between the original.
Native control rendering
Since WebView performance is not good enough, there is a solution to use native controls for rendering. This solution, also developed in JavaScript, is ultimately rendered using native controls. The best example of this is Facebook’s React Native.
Because native controls are used for rendering, the performance experience is also closer to native. But it’s closer, not as good as native, because it requires frequent communication between JavaScript and native, which is relatively inefficient.
In addition, since controls need to be adapted to each platform, it is possible for system controls to be updated while the framework itself has not been updated, causing some problems. In other words, the scheme is limited by native controls.
Drawing engine rendering
And then there’s the main character.
On the front end, if you don’t use native controls at all, you can draw a user interface through the system’s drawing API. From this point of view, it is possible to use a unified interface drawing engine for each platform, which ultimately calls the system API for drawing. This way, its performance can be close to native without being limited by native controls, and the UI can be unified across different platforms.
Flutter is one such development framework.
Introduction of Flutter
A cross-platform UI solution
Flutter is a cross-platform UI solution developed by Google. In other words, it’s basically just about the UI, and if it involves some of the platform’s own functions, such as calling Bluetooth and cameras, it generally needs native code to operate. But now there are third-party libraries to help us solve these problems.
Drawing engine Skia
Flutter uses Skia as its drawing engine. Skia was acquired by Google and is now used to draw many of Google’s products, including Android.
Android has Skia built in, but iOS doesn’t, so when you type in the iOS package, you type in Skia. As a result, the iOS package is larger than the Android package when packaged with the same Flutter code.
Development language Dart
The development language that Flutter uses is called Dart. Dart is also Google’s own, and it’s an object-oriented language that looks a lot like other development languages. It’s not very difficult to learn.
When I talked about cross-platform solutions, I noticed that all other solutions use JavaScript as the development language. Why not Flutter? Because Dart is Google’s own? Leave that for now and we’ll come back to it.
Setting up the development environment
Here is part of the simple point, the specific construction process can be viewed on the official website:
Flutter – IO. Cn/docs/get – st…
The main steps are as follows:
Download the Flutter SDK
Official website download address:
Flutter. Dev/docs/develo…
As access to the country may be limited, officials have set up a mirror image for Chinese developers:
Flutter. Dev/community/c…
Updating environment variables
After decompression, add the full PATH of flutter\bin to the environment variable PATH.
Installing development tools
Theoretically, any text editor can be used to develop Flutter applications, but the recommended development tools are Android Studio, IntelliJ, and VS Code. The official Flutter and Dart plug-ins can be installed on these tools for a better development experience. This article uses Android Studio to demonstrate this.
If you plan to develop an iOS app, you’ll also need to install Xcode.
Installing a plug-in
In the development tool plugin Settings, install the Flutter and Dart plug-ins described above. The Flutter plugin supports Flutter operation, debugging, and thermal overloading, while the Dart plugin provides input verification and code completion.
Hello World!
Everything starts with Hello World. Let’s create a Flutter project that displays Hello World.
Create a new Flutter project by selecting Start a new Flutter Project on the Welcome page of Android Studio, or by going to File > New > New Flutter Project on the menu bar.
The created project contains the Android and ios folders, which are standard Android and ios projects. Our Flutter code is stored in the lib folder. After the project is created, it defaults to an example of a counter, so let’s ignore that and change the main.dart code to Hello World:
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("Hello")),
body: Center(child: Text("Hello World!", style: TextStyle(fontSize: 32))))); }}Copy the code
Start an emulator, or connect to the real machine, click Run to Run it, and you will see an interface like this:
The specific code will look familiar, and we’ll talk about it later.
The Dart grammar
Before writing about Flutter, A brief introduction to Dart’s syntax should be given. If you have Java or JavaScript development experience and object-oriented programming mindset, it’s a quick pick up.
You can create a dart file in the Test folder to write the test code.
Variable declarations
Specify the type
As with Java, we can declare an integer variable like this:
int num = Awesome!;
Copy the code
var
We can also use var declarations like JavaScript:
var num = Awesome!;
Copy the code
But unlike JavaScript, the following code does not return an error in JavaScript, but does return an error in Dart:
var num = Awesome!;
void main() {
num = "666"; / / an error
}
Copy the code
After you declare a variable with var in Dart, it will infer the type of the variable based on the first assignment, and you can’t change the type after that. That said, JavaScript is a weakly typed language and Dart is a strongly typed language.
Object
If that’s what it says up there, fine. Var = Object;
Object num = Awesome!;
void main() {
num = "666";
}
Copy the code
Like Java, Object is the base class for all objects. If num is not the length of the string, it will not be the length of the string.
Object num = Awesome!;
void main() {
num = "666";
print(num.length); / / an error
}
Copy the code
Because length is a String, num is an object, not a String.
dynamic
If you have to write it that way, that’s fine. Dart: Dart: Dart: Dart: Dart: Dart: Dart: Dart: Dart: Dart: Dart: Dart: Dart: Dart: Dart
dynamic num = Awesome!;
void main() {
num = "666";
print(num.length);
}
Copy the code
If we run the file, we can see on the console that the string length is correctly printed.
Dynamic means dynamic, and with this declaration, the system will find available properties and functions to call. But this is actually not very secure, because even if you misspell the property name, the compiler will not report an error until runtime.
function
dynamic
Dart also allows functions to omit their return type, which is treated as dynamic. In this case, the type of the function is the type of return, or void if there is no return. For example:
main() {
print(getNum().length);
}
getNum(){
return "666";
}
Copy the code
This will print the correct length of the string.
Used to transfer and
Dart functions are also objects, so you can pass functions as arguments, such as:
main() {
execute(print666);
}
print666() {
print("666");
}
execute(Function fun){
fun();
}
Copy the code
Optional parameters
The Dart function has a concept called optional parameters. For example, the Text control Text constructor looks like this:
const Text(
this.data, {
Key key,
this.style,
this.strutStyle,
this.textAlign,
this.textDirection,
this.locale,
this.softWrap,
this.overflow,
this.textScaleFactor,
this.maxLines,
this.semanticsLabel,
})
Copy the code
First, in the argument there is a data, which is the text content to display, is a mandatory field. The arguments behind data, enclosed in curly braces, are called optional, meaning they can be passed or not.
If we want to display a long Text and want to limit it to two lines, we can create a Text like this:
new Text("666666666666", maxLines: 2);
Copy the code
Optional parameters, used a lot in Flutter.
asynchronous
Future
Dart uses the Future to handle asynchronous tasks, such as printing 666 with a one-second delay:
void main() {
Future.delayed(new Duration(seconds: 1), () {
return "666";
}).then((data) {
// Execute after success
print(data);
}).catchError((e) {
// Execute after failure
print("error");
}).whenComplete(() {
// Execute regardless of success or failure
print("complete");
});
}
Copy the code
The syntax of Future is very similar to that of Promise. Then is called on success, catchError is called on failure, and whenComplete is called on success or failure.
async/await
If you don’t like the above, or want to convert async to synchronous, you can use async and await.
Let’s convert the above code and write a getString method that returns type Future, which will delay the return of a string. Add async keyword after main and await before getString() as follows:
void main() async{
print(await getString());
}
getString() {
return Future.delayed(new Duration(seconds: 1), () {
return "666";
});
}
Copy the code
As you can see, it prints out the string after a normal delay of one second. Here getString() returns a Future and await getString() returns a delayed string. Await should be used inside async functions.
Async and await are syntactic sugars that are ultimately executed as a chain of Future calls.
Everything control
Coming back to Flutter, one of the most important concepts of Flutter is the Widget.
In native development, we might make a distinction between a View, a Layout, and a View Controller. But inside Flutter, they all belong to a single model Widget. In a sense, everything in the Flutter interface is a Widget.
When we were learning object orientation, we all heard the saying that everything is an object. I’ll apply it here. In Flutter, everything is controlled.
Specific which controls, I did a simple classification.
Root control
class MyPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
returnMyWidget(); }}Copy the code
All controls belong to the StatefulWidget or StatelessWidget. The difference is that the StatefulWidget has State State, while the StatelessWidget does not.
StatefulWidget
When a control is mutable, use the StatefulWidget to build it. The StatefulWidget itself is immutable, but the State State it holds is mutable.
StatelessWidget
StatelessWidget is used when the state of a control is fixed and immutable. Earlier we wrote Hello World using the StatelessWidget.
Container control
Center(
child: MyWidget()
)
Copy the code
Container-class controls generally apply certain properties or configurations to their child controls, such as the width, height, background, location, and so on.
Common Container controls include Container, Center, and Padding.
The layout of the control
Column(children: <Widget>[
MyWidget1(),
MyWidget2()
])
Copy the code
A Layout control can be analogous to a Layout in native development, usually with a children property that receives an array of controls for specific typesetting.
Common layout controls include Row, Column, Stack, Flex, and so on.
Based on the control
Text("666")
Copy the code
Basic controls are commonly used text, buttons, pictures and other controls.
Common basic controls are Text, TextField, Button, Image, and so on.
The function of control
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return NewPage();
}));
Copy the code
There is also a class of controls in Flutter that do not affect the UI layout but have specific functions, such as page hopping, event listening, theme defining, etc. We call this class of controls functional controls.
Common functional controls include Navigator, NotificationListener, Theme, etc.
counter
Start writing code for Flutter. Remember that after the Flutter project was created, there was a counter demo that came with it. Now let’s implement it in our own code. Change the code to the following:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
returnMaterialApp(home: MyPage()); }}class MyPage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
returnMyPageState(); }}class MyPageState extends State<MyPage> {
int num = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Counter"),
),
body: Center(
child: Text(
num.toString(),
style: TextStyle(fontSize: 36)
)
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
setState(() {
num++;
});
}));
}
}
Copy the code
After running, you should see something like this:
Each time the button is clicked, the number increases by one. Let’s take a look at the code and take a look at some of the widgets used.
StatefulWidget
Because the numbers on the page follow the state, the page is switched to the StatefulWidget. StatefulWidget does not return a Widget directly. Instead, StatefulWidget returns State, where the Widget is returned.
Scaffold
The Scaffold is a standard Material Design page with title bars, float buttons, slide-out menus, bottom navigation bars and more. We use the title bar appBar, the page content Body, and the floatingActionButton.
AppBar
AppBar is the title bar, and you can see its configurable properties by looking at the constructor of the control.
The optional parameters of AppBar include title, leading before title, anctions on the right, and elevation of controls. We just pass in the title and use the default values for all the other attributes.
Center
Center is a container control that centers its child controls.
FloatingActionButton
For those familiar with Android development, this control should be familiar. It is a Button with a specific style in the bottom right corner of the page. The onPressed parameter is a required field to pass a callback function after being clicked.
Based on this example, there are two important properties of Flutter.
Responsive UI
After clicking the Button, we increment the num variable by one and use setState to notify that the state has changed. The Flutter updates the UI based on the new state. If you’re familiar with applets, setState is similar to setData for applets.
There is no need to update the UI with a set method in Flutter. Mutable controls are bound to state. This is responsive UI programming for Flutter.
Thermal overload
Dark mode has been added to Both Android Q and iOS 13, so let’s switch to a dark theme. There is a theme property in the MaterialApp, let’s configure it:
return MaterialApp(
theme: ThemeData.dark(),
home: MyPage()
);
Copy the code
Instead of clicking Run, we can click on the lightning icon, Flutter Hot Reload, to see that the interface has changed:
This is the thermal reloading of Flutter. After code changes are made, the changes can be seen on the device immediately by thermal reloading, greatly increasing development efficiency.
Here are some more common actions of Flutter.
Page jump
In Flutter, use a Navigator to manage page transitions. For example, to jump to a NewPage, you can write:
Navigator.of(context).push(MaterialPageRoute(builder: (context) {
return NewPage();
}));
Copy the code
Push is used for pushing and pop is used for popping.
MaterialPageRoute simulates the cut-scene effect of page jumps on Android.
Local image
Let’s see how to display a local image.
Create an image folder in your root directory, such as images, and put the picture picture.png inside it.
Find the file pubspec.yaml in the root directory. This is the Flutter dependency configuration file.
assets:
- images/picture.png
Copy the code
Now we can display the Image using the Image control:
Image.asset("images/picture.png"))
Copy the code
Introducing third-party libraries
Just like Node’s NPM and Android’s JCenter, Flutter also has a public repository, pub.dev. Pub. dev is Google’s official Dart repository, where you can find the packages and plug-ins you need.
Flutter itself does not have toasts. Let’s access one. After searching on pub.dev, I decided to use Fluttertoast:
Configure it under Dependencies in the pubspec.yaml file as instructed:
Fluttertoast: ^ 3.1.0Copy the code
Click on the Packages Get in the upper right corner of Android Studio to sync and use it:
Fluttertoast.showToast(msg: "666666");
Copy the code
IOS style
All the Material Design controls we used above are included in the flutter/ Material. Dart package. To use ios-style controls, use the flutter/ Cupertino. dart package:
import 'package:flutter/cupertino.dart';
Copy the code
Most ios-style controls start with Cupertino. Let’s replace the controls in the timer page:
import 'package:flutter/cupertino.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CupertinoApp(home: MyPage());
}
}
class MyPage extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return MyPageState();
}
}
class MyPageState extends State<MyPage> {
int num = 0;
@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text("Counter"),
),
child: Container(
width: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(num.toString(), style: TextStyle(fontSize: 36)),
CupertinoButton(
color: CupertinoColors.activeBlue,
child: Icon(CupertinoIcons.add),
onPressed: () {
setState(() { num++; }); })],))); }}Copy the code
The effect is as follows:
Compile the way
So that’s the end of the code, and I’m going to talk a little bit about how to compile. There are two ways to compile in a programming language.
-
JIT (Just in time) – Compile while running
-
AOT (Ahead of time) – Compile first, then run
They are better or worse, it depends on which Angle to compare. One of the features of JIT is that it supports dynamic publishing of code, that is, hot updating. But from a performance standpoint, AOT is better because it runs more efficiently without having to compile.
Returning to the question we left at the beginning, why should Flutter be developed using Dart when all other cross-platform solutions are in JavaScript? JavaScript is compiled JIT and does not support AOT. Dart supports both JIT and AOT.
The USE of JIT in Flutter development allowed us to use thermal overloading and increased development efficiency. Switching to AOT during packaging ensures the performance of the official application.
Hot update?
Finally, one thing that you’re interested in, does Flutter support thermal renewal? Dart supports JIT, so technically it does. However, it is not supported at present, as can be seen in the official planning document:
As for the reasons, the official explanation here. Generally speaking, due to policy restrictions, as well as performance and security concerns, it is not supported for the time being.
The end of the
That’s it. Since I want to cover the basics of Flutter in one article without going into too much detail, I still need to learn more if I want to write the Flutter code. But I believe that understanding after learning, will be a lot easier.
No problem.