Before developing FlutterApp, we must first understand Dart and its features and syntax. I’ve seen a lot of them lately
The Dart language is described in this chapter. directory
- Concepts and Advantages
- variable
- function
- closure
- Asynchronous support
Concepts and Advantages:
- Dart: Google and other developers around the world use Dart to develop a range of high-quality, critical iOS, Android, and Web apps. Dart is ideal for mobile and Web application development.
1. The efficient
Dart syntax is clear and concise, and tools are simple and powerful. Input detection helps you identify subtle errors early. Dart has proven core libraries and an ecosystem that already has thousands of packages
2. Rapid
Dart provides pre-compile optimization for predictable performance and fast startup on mobile devices and the Web.
3. Portable
Dart can be compiled to ARM and x86 code, so Dart mobile applications can run natively on iOS, Android, and later. Dart can be converted to JavaScript for Web applications.
4. Easy to learn
Dart is an object-oriented programming language with a syntax style that will be familiar to many existing developers. Dart is easy to use if you know Java and JS, and has some of the features of Swift.
5. Response type
Dart makes responsive programming easy. Dart is more efficient for managing short-term objects, such as UI widgets, thanks to fast object allocation and the implementation of the garbage collector. Dart enables asynchronous programming through Future and Stream features and apis.
variable
- Var automatically infers the type (unlike OC or Java) and accepts variables of any type, but once assigned, the type cannot be changed, i.e., it was originally a string and then a string (unlike JS).
var a = "String"; // If this is the case, an error will be reported, and the type cannot be changed after the first specified a = 1;Copy the code
Dart is a strongly typed language, and any variable has its own type. The type of the variable is inferred at compile time based on the type of the data first assigned, and the type cannot be changed after compile. JS is a purely weakly typed scripting language, and var is just a declaration of variables.
- dynamic
Dynamic, like var, is a keyword. Declared variables can be assigned to objects of any type. Declared variables can change assignment types later. It’s a string that can then be assigned to a number or something else.
dynamic a = "String"; A = 1;Copy the code
- Object
Object, like Dynamic, is a declared variable that can be assigned to any type of Object. Declared variables can change the assignment type later.
Object b = "hello world"; // b = 10;Copy the code
The difference is that the compiler for objects declared with Dynamic provides all possible combinations, or at least no errors (although it is possible that the runtime will crash because it cannot find the prefabricated combinations), whereas the compiler for objects declared with Object can only use Object properties and methods, otherwise the compiler will report errors.
dynamic a = "";
Object b = ""; // The compiler does not report errors or warnings.print(a.length); // The compiler will warn of an error (Object does not have a getter for length) : The getter'length' is not defined for the class 'Object'
print(b.length);
Copy the code
Note: Dynamic can be interpreted as the id type, any type can be converted to id (dynamic), can use ID (dynamic), the compiler does not error, but may cause a crash at runtime.
- final
Final is a run-time constant.
Constants that are final must be initialized when they are declared, and their value cannot change after initialization
final a = "Name"; // error a ="Gender";Copy the code
- const
Const is a compile-time constant. Const can declare not only constant variables, but also constant values and constructors that create constant values. Any variable can have a constant value.
Final aList = const[]; Const bList = const[]; Var cList = const[]; Where aList and bList are two empty, immutable list sets, cList is an empty, mutable list set; Note that cList can be reassigned and changed, while aList and bList cannot be reassigned;Copy the code
- The Dart Function is an object-oriented language, so even functions are objects and have a type Function. This means that functions can be assigned to variables or passed as arguments to other functions, a typical feature of functional programming.
1. Function declaration
Return type method body (parameter 1, parameter 2...) {method body...returnReturn value} String getPerson(String name, int age){return name + '${age}'; } // If the return type is not specified, the default is dynamic.Copy the code
2. Arrow function
For functions that contain only one expression, you can use shorthand syntax.
getPerson(name, age) => name+ ', $age'; Bool isNoble (int atomicNumber)=> _nobleGases [atomicNumber]! = null ;Copy the code
3. Function as variable (method object), input parameter
// function as variable var method1 = (STR) {print(str)
};
method1("kakalala"); Void execute(var callbackMethod){callbackMethod(); } // Execute (() =>print("xxx"));
execute(method1("kakalala"));
Copy the code
4. Optional parameters (optional location parameters, optional named parameters)
- Optional position parameters: [param1, param2,…] , you can set default arguments to wrap a set of function arguments, mark them with [] as optional positional arguments, and place them at the bottom of the argument list:
getPerson(String name, [int age = 99, String gender = "Royal elder sister"]) {print ("name = $name, age = $age, gender = $gender"); } //getPerson() ; This is an error. getPerson(null) ; getPerson('Don't know fire'); getPerson('Don't know fire', 100);
getPerson('Don't know fire', null, "Girl");
Copy the code
Console output
Flutter: name = null, age = 99, gender = name, age = 99, gender = Name = no fire, age = 100, gender = no fire, age = null, gender = girlCopy the code
Note: The name argument must be passed in, otherwise an error will be reported. The following optional position argument will be null if not passed, and will return NULL if passed. Optional location parameters can be set to default parameters.
- Optional named parameters: {param1, param2… } When passed in, you need to specify the corresponding parameter name, which is placed at the end of the parameter list to specify the named parameter. You can set default parameters.
getPerson(String name, {int age = 100, String gender = "Dog"{})print("name = $name, age = $age, gender = $gender"); } //getPerson() ; This is an error. getPerson(null) ; getPerson('Before the Fire of jade Algae'); getPerson('Before the Fire of jade Algae', age: 99 );
getPerson('Before the Fire of jade Algae', gender: "Royal elder sister" );
getPerson('Before the Fire of jade Algae', age: 99, gender: "Milk dog");
Copy the code
Console output:
Flutter: name = null, age = 100, gender = dogs flutter: name = embers, age = 100, gender = dogs flutter: name = embers, age = 100, gender = dogs flutter: Name = embers, age = 99, gender = dog flutter: name = embers, age = 100, gender = sister flutter: Name = name, age = 99, gender = milk dogCopy the code
Note: fixed arguments must be passed (even if null is passed). Optional named arguments can be set to default arguments.
- Default Parameter Value
The default argument value is that we pass a constant value in the method argument list with the “=” sign, and if no value is passed in, the constant value we pass in is used.
Note that you cannot use both an optional positional parameter and an optional named parameter
// This is not possible, false example. getPerson(String name, {int age = 100, String gender ="Dog"}, [int age2 = 1002, String gender2 = "German shepherd 2"]){
}
Copy the code
closure
A closure is a method (object) defined inside another method that can access local variables of an external method and hold their state.
void mainFunction add1 = addNum(2); Function add1 = addNum(2); Function add2 = addNum(4); Function add2 = addNum(4); // 2 + 3 = 5print(add1(3));
// 4 + 3 = 7
print(add2(3)); } Function addNum(int addBy){Function addNum(int addBy){return (int i) => addBy + I;
}
Copy the code
Console output:
flutter: 5
flutter: 7
Copy the code
Asynchronous support
The Dart code runs on a single thread, and if the Dart code blocks – for example, the program takes a long time to evaluate, or waits for I/O – the entire program freezes.
Dart asynchronous functions: Future, Stream, return after setting time-consuming operations, do not block the thread.
The async and await keywords support asynchronous programming, allowing you to write asynchronous code that looks a lot like synchronous code.
Future
Future is very similar to Promise in JS and RXSwift in that its syntax is also a chained function call, which, after an asynchronous operation is executed, eventually returns success (successful operation is performed) or failure (failure is caught or subsequent operation is stopped). Failure and success are opposite and only one can occur.
Note: The return value of all Future apis is a Future object, so you can make chain calls.
- Future constructor
Future(FutureOr Computation ()) Computation can return a common value or a Future object, but the Future object will accept both
Future<num> future1 = Future(() {
print('async call1');
return123; }); // Call future1.then((data) {// Successful execution will go hereprint(data);
}, onError: (e) {
print("onError: \$e"); }).catchError((e)print(e); }). WhenComplete (() {// Success or failure will come here}); Future<Future> future2 = Future((){print('async call2');
returnfuture1; }); Future2.then ((value) => value).then((value) => {print('222 -'+value.toString())
});
Copy the code
Console printing
Reloaded 1 of 499 libraries in 154ms.
flutter: async call1
flutter: 123
flutter: async call2
flutter: 222---123
Copy the code
Note that code in the Computation body is executed asynchronously, unlike the callback timing of the Promise constructor in JS. If it needs to be executed synchronously, the following named constructor is used:
Future.sync(FutureOr computation())
Future3 = future.sync ((){Future<num> future3 = future.sync (){print('sync call');
return 333;
});
future3.then((value) => {
print('sync'+'$value')});Copy the code
Console output
flutter: sync call
flutter: sync333
flutter: async call1
flutter: 123
flutter: async call2
flutter: 222---123
Copy the code
As you can see, the future3 (sync) method is executed first, followed by future1 and future2. You can see that code in the computation body of a normal Future is executed asynchronously.
- Future.then Then receives asynchronous results
Future.delayed(new Duration(seconds: 2),(){
return "Delayed execution of 2s";
}).then((data){
print(data);
});
Copy the code
- Future.catchError
Capture the error
Future.delayed(new Duration(seconds: 2),(){
//return "Delayed execution of 2s";
throw AssertionError("Error"); }).then((data){// Successful execution will go hereprint("success"); }).catchError((e)print(e);
});
Copy the code
If an exception is thrown in an asynchronous task, the then callback will not be executed and the catchError callback will be called; Not only does the catchError callback catch errors, but the then method also has an optional argument onError (mentioned earlier when introducing constructs), which can also catch exceptions:
Future.delayed(new Duration(seconds: 2), () {
//return "Delayed execution of 2s";
throw AssertionError("Error");
}).then((data) {
print("success");
}, onError: (e) {
print(e);
});
Copy the code
- Future.whenComplete
This method is called in scenarios where events are handled regardless of success or failure, such as popping up a load dialog before a network request and closing the dialog after the request ends. There are two ways to do this. The first is to close the dialog in then or catch, respectively, and the second is to use the whenComplete callback of the Future:
Future.delayed(new Duration(seconds: 2),(){
//return "Delayed execution of 2s";
throw AssertionError("Error"); }).then((data){// Successful execution will go hereprint(data); }).catchError((e)print(e); }). WhenComplete ((){// Success or failure will come here});Copy the code
- Future.wait
We need to wait for the completion of multiple asynchronous tasks before performing some operations (for example, we have an interface that needs to obtain data from two network interfaces respectively. After obtaining data successfully, Future.wait does this (similar to RXswift’s zip function). It takes an array of futures. the success callback for then is triggered only when all futuresin the array have been successfully executed. Every time a Future fails, an error callback is triggered.
Future4 = future. wait(future.delayed (new Duration(seconds: 2), () {future.delayed (new Duration(seconds: 2), () {future.delayed (new Duration(seconds: 2), () {return "Delayed execution of 2s"; }), // future.delayed (new Duration(seconds: 4), () {return "Delayed execution by 4s";
})
])
future4.then((value) => {
print(value[0]+ value[1]);
}).catchError((e){
print(e);
});
Copy the code
Console output
// Wait for 4s output flutter: delay the execution of FLUTTER by 2sCopy the code
- There is a lot of asynchronous logic in Callback Hell code, and when a lot of asynchronous tasks depend on the results of other asynchronous tasks, a Callback within a Callback is inevitable. We need to use async/await and future. then to solve this problem. Usage scenario: a large number of dependent business logic, logon flow logic, etc.
Future<String> future1(String str1){... // First task}; Future<String> future2(String str2){ ... // Second task}; Future future3(String info){ ... // The third task}; future1("str1").then((str2){//1 returns data as 2 parameter future2(str2). Then ((info){//2 returns data as 3 parameter future3(info). Then ((){// 3 returns data as 3 parameter future3(info). }); }); })Copy the code
The Future elimination Callback Hell uses the Chain mechanism of the Future to work its way down to avoid nesting. It’s exactly the same as JS Promise. The downside is that there is still a layer of callback.
future1("str1").then((str2){
return future2(str2);
}).then((info){
returnfuture3(info); }). Then ((e) {/ / 3 the next operation on}). CatchError ((e) {/ / error handlingprint(e);
});
Copy the code
The async/await method eliminates callback hell while avoiding nesting, there is still a layer of callback for each method. We can use async/await to perform asynchronous tasks like synchronous code without using callbacks.
task() async {
try{
String str2 = await future1("str1"); String info = await future2(str2); await future3(info); } catch(e){// Error handlingprint(e); }}Copy the code
- Async /await async is used to indicate that a function is asynchronous. The defined function returns a Future object. Callbacks can be added using the then method
“Await” is followed by a Future, which means to wait for the asynchronous task to complete and then proceed. Await must appear inside async function.
Async /await represents an asynchronous stream in synchronous code.
Async /await is just a syntactic sugar that the JS compiler or Dart interpreter will eventually convert into a JS Promise and a chain of calls to Dart’s Future.
Stream
If a Future can receive a single asynchronous event and return the successful failure of a single event, then a Stream can receive multiple asynchronous events and return the successful failure of multiple events for consumption. Usage scenario: Asynchronous task scenarios where multiple data reads are performed, such as network content download and file read and write. This example uses examples from other places.
Future.delayed(new Duration(seconds: 1), () {return "hello 1"; }), // throw an exception future.delayed (new Duration(seconds: 2),(){throw AssertionError()"Error"); }), // future.delayed (new Duration(seconds: 3), () {return "hello 3";
})
]).listen((data){
print(data);
}, onError: (e){
print(e.message);
},onDone: (){
});
Copy the code
Console output
flutter: hello 1
flutter: Error
flutter: hello 3
Copy the code
Future.wait is a function that has multiple delayed operations. The longest delayed operation will be returned after completion, and other delayed operations will wait for the longest delayed operation to complete.
Async /await: handle multiple asynchronous operations with dependent logic before and after them. Use asynchrony to achieve synchronization.
Stream: Uniformly listens for the return of multiple asynchronous delayed operations in this Stream, similar to the unified listening for multiple asynchronous futures before.
- Among them, Future and Stream only introduce common methods and functions, and more detailed summaries will be made later.
Dart syntax and attribute methods are commonly used in Dart syntax and attribute methods. If you have errors or do not understand them properly, you can raise them and make progress together.
Dart has many advantages over Java and JavaScript. Dart can be used for server-side scripting, APP development, and Web development.