I am planning to pit Flutter recently, so I will record it here and check it as needed;
Don’t be cool, just do it,
A simple Dart program
// the 🐷 function, where the application starts
main(){
var number = "Hello World";
printInteger(number);
}
// Define a function
printInteger(int aNumber){
print('The number is $aNumber');
}
Copy the code
Important concepts
When learning the Dart language, you should base your learning on the following facts and concepts
- Anything stored in a variable is an object; All objects correspond to an instance of a class, functions and NULL are objects, and all objects are based on the Object class
- Dart is strongly typed, but Dart can do type inference, such as the code variable number being inferred to be of type int. To specify that no type is required, use the special type Dynamic
- Dart supports generics, such as List, List(List of objects of any type)
- Dart supports the top-level function main(), again bound to a class or object (respectivelyStatic functions 和 Examples of function). And support for creating functions within functions (nested 或 Local function).
- Dart supports top-level variables
- Dart does not have the keywords public, protected, and private, and is private relative to the library if it begins with _
- Ternary operators: condition? Expr1 : expr2
- Type problems: warnings and errors. Warnings indicate that the code may not work properly, but do not prevent the program from executing. Errors may be compilation or runtime errors.
The keyword
abstract 2 | dynamic 2 | implements 2 | show 1 |
---|---|---|---|
as 2 | else | import 2 | static 2 |
assert | enum | in | super |
async 1 | export 2 | interface 2 | switch |
await 3 | extends | is | sync 1 |
break | external 2 | library 2 | this |
case | factory 2 | mixin 2 | throw |
catch | false | new | true |
class | final | null | try |
const | finally | on 1 | typedef 2 |
continue | for | operator 2 | var |
covariant 2 | Function 2 | part 2 | void |
default | get 2 | rethrow | while |
deferred 2 | hide 1 | return | with |
do | if | set 2 | yield 3 |
These words should be avoided as identifiers
- Words with a 1 are context keywords that have meaning only in a specific place, and they are valid identifiers everywhere
- Those with a 2 are built-in identifiers. These keywords are valid identifiers in most places and cannot be used for type names and import prefixes
- The ones with the 3 are updates related to asynchronous support that were added after Dart 1.0 as restricted class reserved words.
variable
var name = "345"; // Create a variable and initialize
dynamic name = "345"; // Name is inferred to be a String
String name = "345";// Explicitly declare
Copy the code
Dynamic: This type has all the possible properties and methods. A variable is decorated with dynamic, which tells the system I know what this type is. The type of the data is not inferred at post-compile time, but at runtime.
The default value
The default value for uninitialized variables is NULL, even for numeric types. Everything is an object in Dart
Final and Const
Variables that are never modified during use can be final or const. The value of a final variable can only be set once; const variables are fixed at compile time.
Built-in types
-
Number: there are two types: 1, int, integer value not greater than 64 bits; Double A floating-point double
-
The String: : Dart String is a sequence of UTF-16 units. The String is created using either single or double quotation marks
You can use + to concatenate strings into one; Multi-line string objects can be created using three or three double quotes
Using the r”” prefix, you can create “raw string”
-
Boolean: true and false
-
List :(also known as Array)
var list = [1, 2, 3]; var list = [1, 2, 3]; assert(list.length == 3); assert(list[1] == 2);
list[1] = 1; assert(list[1] == 1);
Add the const keyword before list to define compile-time constants of type list
var constantList = const [1, 2, 3]; Copy the code
-
Map: used to associate keys and values. A key can appear only once in a Map
var gifts = { // Key: Value 'first': 'partridge', 'second': 'turtledoves', 'fifth': 'golden rings' }; Copy the code
-
Set: A Set is a unique Set of elements
var halogens = {'fluorine', 'chlorine', 'bromine', 'iodine', 'astatine'}; var names = <String>{}; // Set<String> names = {}; // This is ok. // var names = {}; // This creates a Map instead of a Set. var elements = <String>{}; elements.add('fluorine'); elements.addAll(halogens); var gifts = Map(); gifts['first'] = 'partridge'; gifts['second'] = 'turtledoves'; gifts['fifth'] = 'golden rings'; var nobleGases = Map(); nobleGases[2] = 'helium'; nobleGases[10] = 'neon'; nobleGases[18] = 'argon';Copy the code
-
Rune: (used to represent Unicode characters in strings)
In Dart, Rune is used to represent UTF-32 encoded characters in strings
A common way to indicate a Unicode encoding is, \uXXXX, where XXXX is a 4-bit hexadecimal number. For example, the heart symbol (♥) is \ U2665. For special cases that are not four values, place the coded value in curly braces. For example, the smiley face (�) is \u{1f600}.
-
Symbol
The Symbol object represents the declared operator or identifier in the Dart program, and you won’t normally use it
Null-aware
Dart null-aware comes from the official Dart 1.12 release, and it is reasonable to have such an operator, which means it saves our code to some extent
The entire operator is dedicated to handling null values, which provide operations on null Pointers
// if b is not null, then b is assigned to A, otherwise C is assigned to A
a = b ?? c;
// If a is null, b is assigned to A
a ?? = b;
// Fun is called when x is not nula? .fun();Copy the code
function
Dart is a true object-oriented language, even functions are objects and have their own type functions. This means functions can be assigned to variables or passed as arguments to other functions, or instances of the Dart class can be called as methods
// omit the type declaration, the function can be used normally
isNoble(atomicNumber) {
return_nobleGases[atomicNumber] ! =null;
}
// If you have only one sentence, you can write succinct
bool isNoble(intatomicNumber) => _nobleGases[atomicNumber] ! =null;
Copy the code
=> *expr* syntax {return *expr*; }. The => notation is sometimes called arrow syntax, where an arrow can only be followed by an expression;
-
This parameter is optional when invoked
When defining functions, use {param1,param2… }, at the end of the argument list, to specify optional arguments, for example
const Scrollbar({Key key, @required Widget child,bool bold})
Copy the code
Using @required indicates that the parameter is a named parameter of required nature.
-
Location This parameter is optional
String say(String from, String msg, [String device]) { var result = '$from says $msg'; if(device ! =null) { result = '$result with a $device'; } return result; } Copy the code
Place the parameter in [] to indicate that the parameter is optional. Indicates that the parameter can not be transmitted
-
Default Parameter Value
// bold is true; Hidden value is false. void abc(bool bold = false); Copy the code
void doStuff( {List<int> list = const [1.2.3].Map<String.String> gifts = const { 'first': 'paper'.'second': 'cotton'.'third': 'leather'{}}})Copy the code
Accepts a list and map and specifies default values for the parameters
-
The main () function
void main(){ } Dart args. Dart 1 test void main(List<String> arguments) { print(arguments); } Copy the code
The main function returns a null value and takes an optional List
-
Anonymous functions
Dart can create functions that have no names. These functions are called anonymous functions. ** is sometimes called a lambda or closure. ** Anonymous functions can be assigned to a variable, for example, anonymous functions can be added or removed from a collection
main(){ var list = []; list.add(1); list.add(2); list.add(3); list.add(4); list.forEach((num) {print('the position:${list.indexOf(num)}; Value:$num'); }); } Copy the code
The above defines an anonymous function with no type parameter num. The list is called each time and the value is passed to the anonymous function.
If there is only one sentence, write as follows:
list.forEach((num) = >print('the position:${list.indexOf(num)}; Value:$num')); Copy the code
-
Assignment and passing of functions
main(){ // Assign an anonymous function to a variable var one = (num) = >print('value:$num'); one(10); // Assign a normal function to a variable var two = abc; two(20); // Pass anonymous functions to ordinary functions abc2((str) => print("abc $str")); } void abc2(fun(String str)){ fun("Output -------"); } void abc(num) {print("Hahaha:$num"); } Copy the code
-
Lexical scope
Dart is a lexical scoped programming language.
Simply put, the scope of a variable is defined at the time of writing the code, and the visible scope of the variable is in curly braces
bool topLevel = true; void main() { var insideMain = true; void myFunction() { var insideFunction = true; void nestedFunction() { var insideNestedFunction = true; assert(topLevel); assert(insideMain); assert(insideFunction); assert(insideNestedFunction); }}}Copy the code
All variables can be accessed internally, up to the variables in the top-level scope.
-
Lexical closures
A closure is a function object. Even if a function is called outside its original scope, it can still access variables in its lexical scope
/// Returns a function whose arguments are added to [addBy]. Function makeAdder(num addBy) { return (num i) => addBy + i; } void main() { // create a function that adds 2. var add2 = makeAdder(2); // create a function that adds 4. var add4 = makeAdder(4); assert(add2(3) = =5); assert(add4(3) = =7); } Copy the code
-
Tests whether the functions are equal
void foo() {} // Top-level function class A { static void bar() {} // Static method void baz() {} // Sample methods } void main() { var x; // Compare top-level functions. x = foo; assert(foo == x); // Compare static methods. x = A.bar; assert(A.bar == x); // Compare instance methods. var v = A(); // The first instance of A var w = A(); // Instance number 2 of A var y = w; x = w.baz; // The same instance referenced by both closures (number 2), // So they are equal. assert(y.baz == x); // Two closures reference different instances, // So they are not equal. assert(v.baz ! = w.baz); }Copy the code
-
The return value
All functions return a value. If there is no explicit return value, the function implicitly adds a return NULL. statements
Extension functions, attributes
StringExtension:extension StringExt on String {
double toDouble() {
return double.parse(this);
}
int toInt() {
return int.parse(this); }}ObjectExtension:extension ObjectExt on Object {
bool isNullOrEmpty() {
if (this is String)
return (this as String).isEmpty;
else if (this is 可迭代) return (this as 可迭代).isEmpty;
return this= =null; }} Generic extension:extension AllExt<T> on T {
T apply(f(T e)) {
f(this);
return this;
}
R let<R>(R f(T e)) {
return f(this); }}// Extend attributes
extension SizeExtension on num {
double get w => 10.0;
double get h => 10.0;
}
Copy the code
The operator
-
Dart defines the following operators:
Description Operator One yuan suffix *expr*++
*expr*--
(a)
[]
.
? .
One yuan prefix -*expr*
! *expr*
~*expr*
++*expr*
--*expr*
multiplicative *
/
%
~ /
additive +
-
shift <<
>>
>>>
bitwise AND &
bitwise XOR ^
bitwise OR ` relational and type test > =
>
< =
<
as
is
is!
equality = =
! =
logical AND &&
logical OR ` if null ??
conditional *expr1* ? *expr2* : *expr3*
cascade .
assignment =
* =
/ =
+ =
- =
& =
^ =
etc.In the table above, most operators can be overloaded
-
Conditional expression
*condition* ? *expr1* : *expr2* Copy the code
If the condition is true, execute expr1 (and return its value) : otherwise, execute and return the value of expr2.
*expr1* ?? *expr2* Copy the code
Return the value of expr1 if expr1 is non-null; Otherwise, execute and return the value of expr2.
-
Cascade operator
Cascade operators can perform operations on an object, call functions, and access field properties on the same object.
void main() { newA() .. a1() .. a2(); }class A{ void a1(){ print('a1'); } void a2(){ print('a2'); }}//a1 a2 Copy the code
Cascade operators can be nested
finaladdressBook = (AddressBookBuilder() .. name ='jenny' ..email = '[email protected]'. phone = (PhoneNumberBuilder() .. number ='415-555-0100' ..label = 'home') .build()) .build(); Copy the code
Control flow statement
-
if
andelse
-
for
loopsfor (var i = 0; i < 5; i++) { message.write('! '); } Copy the code
You can also use forEach, or for-in
candidates.forEach((candidate) => candidate.interview()); Copy the code
var collection = [0.1.2]; for (var x in collection) { print(x); / / 0 1 2 } Copy the code
-
while
anddo
–while
loops -
break
andcontinue
-
switch
andcase
Similar to Java, you can compare integers, strings, or compile-time constants to the same instance (and not subclasses), and enumerations can use switch statements
-
assert
If the Boolean condition in Assert is false, the normal program execution flow is interrupted
Assert statements are valid only in the development environment, not in production
abnormal
Dart can throw and catch exceptions, or if none are caught, they will be thrown, ultimately causing the program to terminate
Unlike Java, all exceptions in Dart are not checked for exceptions. Methods do not declare the exceptions they throw, nor are they required to catch any
Dart provides the Exception and Error types, as well as several subtypes. You can also customize the exception type. In addition, the Dart program can throw any non-NULL object, not just Exception and Error objects.
-
throw
throw FormatException('Expected at least 1 section'); Copy the code
-
Throw an arbitrary object
throw 'Out of llamas! '; Copy the code
-
Throw an exception where the expression is used
void distanceTo(Point other) => throw UnimplementedError(); Copy the code
-
Catch
Catch exceptions
try { breedMoreLlamas(); } on OutOfLlamasException { // a special exception buyMoreLlamas(); } on Exception catch (e) { // Any other exceptions print('Unknown exception: $e'); } catch (e) { // No specified type, handle all exceptions print('Something really unknown: $e'); } Copy the code
The catch function can specify 1 or 2 parameters, the first being the exception object and the second being the StackTrace object.
try { / /... } on Exception catch (e) { print('Exception details:\n $e'); } catch (e, s) { print('Exception details:\n $e'); print('Stack trace:\n $s'); } Copy the code
If some exceptions need to be handled, you can use rethrow to rethrow the exception
void misbehave() { try { dynamic foo = true; print(foo++); // Runtime error } catch (e) { print('misbehave() partially handled ${e.runtimeType}. '); rethrow; // Allow callers to see the exception.}}void main() { try { misbehave(); } catch (e) { print('main() finished handling ${e.runtimeType}. '); }}Copy the code
-
finally
Finally is executed whether or not an exception is tried. If a try holds an exception, the corresponding catch is executed first, and finally
class
Dart is an object-oriented language based on class and mixin inheritance. Each Object is an instance of a class, and all classes inherit from Object. Based on * Mixin inheritance * means that each class (except Object) has only one superclass, and code in one class can be reused in multiple other inherited classes.
-
Create an object
var p = Point(2.2); // Set the value of the instance variable y. p.y = 3; // Get the value of y. assert(p.y == 3); // If p is not empty, set y=8p? .y =8 // Call p's distanceTo() method. num distance = p.distanceTo(Point(4.4)); Copy the code
Use? . Instead of. To avoid exceptions caused by the possibility that the left object is null
-
Getting the object type
The Type of the object can be obtained at runtime using the object’s runtimeType property, which returns a Type object.
-
The instance variables
class Point { num x; // Declare a sample variable x with an initial value of null. num y; // Declare the example variable y with an initial value of null. num z = 0; // Declare a sample variable z with an initial value of 0. } Copy the code
Uninitialized variables are null
Getter methods are implicitly generated for all instance variables, and setter methods are generated for non-final variables
-
The default structure
Dart provides a default construct when no construct is declared
-
Constructors are not inherited
Subclasses do not inherit the constructor of their parent class. A subclass does not declare a constructor, so it has only a default constructor (anonymous, no arguments).
-
Named constructor
We can use named constructors to implement multiple constructors for a class. We can also use named constructors to more clearly indicate the purpose of a function:
class Point { num x, y; Point(this.x, this.y); // Name the constructor Point.origin() { x = 0; y = 0; }}Copy the code
Remember that constructors cannot be inherited, which means that the named constructor of the parent class cannot be inherited by subclasses. If you want to create a subclass using a named constructor defined in the parent class, you must implement that constructor in the subclass.
-
Call the parent field default constructor
The execution sequence is as follows:
- Initializer List (List of initialization parameters)
- Superclass’s no-arg constructor (nameless constructor for superclass)
- Main class’s no-arg constructor main class’s no-arg constructor
class Person { String firstName; Person.fromJson(Map data) { print('in Person'); }}class Employee extends Person { // Person does not have a default constructor; // you must call super.fromJson(data). Employee.fromJson(Map data) : super.fromJson(data) { print('in Employee'); } } main() { var emp = new Employee.fromJson({}); // Prints: // in Person // in Employee if (emp is Person) { // Type check emp.firstName = 'Bob'; } (emp as Person).firstName = 'Bob'; } Copy the code
-
Constant constructor
If your class creates objects that never change, you can create constant instances at compile time, define constant constructors, and make sure that all member variables are final.
var p = const ImmutablePoint(2.2); Copy the code
Create a compile-time constant by prefacing the constructor name with a const shutdown word
Note: Constructing two identical compile-time constants produces an identical instance
In the context of constants, const can be omitted:
// There are many const keywords here. const pointAndLine = const { 'point': const [const ImmutablePoint(0.0)].'line': const [const ImmutablePoint(1.10), const ImmutablePoint(2 -.11)]};Copy the code
// There is only one const that establishes the constant context. const pointAndLine = { 'point': [ImmutablePoint(0.0)].'line': [ImmutablePoint(1.10), ImmutablePoint(2 -.11)]};Copy the code
In Dart2, a const keyword in a constant context can be omitted
class ImmutablePoint { static final ImmutablePoint origin = const ImmutablePoint(0.0); final num x, y; const ImmutablePoint(this.x, this.y); } Copy the code
-
Factory constructor
class Logger { final String name; bool mute = false; // As can be seen from the named _, // _cache is private. static final Map<String, Logger> _cache = <String, Logger>{}; factory Logger(String name) { if (_cache.containsKey(name)) { return _cache[name]; } else { final logger = Logger._internal(name); _cache[name] = logger; return logger; } } Logger._internal(this.name); void log(String msg) { if(! mute)print(msg); }}Copy the code
In fact, it is a factory pattern, pass as the name of the corresponding, and then get the corresponding instance
-
About the others
Abstract classes, enumerations, I’m not going to go into detail here, these are all basic operations, just like Java. If you do not understand, you can go to the official website to check
Asynchronous operations
-
Future
void main() { print("start ----------->"); print(getNetData()); print("end -------------->"); } String getNetData() { // Takes 3 seconds sleep(Duration(seconds: 3)); return "Network data"; } Copy the code
Start -- -- -- -- -- -- -- -- -- -- - > F / / takes three seconds, printed below Network data end -- -- -- -- -- -- -- -- -- -- -- -- -- -- >Copy the code
As you can see, the main method blocks directly, preventing subsequent code execution, which must be a problem
Asynchronous network request
Future<String> getNetData() { return Future(() { sleep(Duration(seconds: 3)); return "Network data"; }); } Copy the code
start -----------> Instance of 'Future<String>' end --------------> Copy the code
The future object is used to place time-consuming operations in functions that pass in parameters
You can see that there is no blocking, but the result returned is an instance of the Future. With a future, you can isolate time-consuming operations without affecting the execution of the main thread.
Get the result of the future
// When a future returned by getNetData returns a result, the function passed in then is automatically called // This function will be executed in an event loop getNetData().then((value) { print(value); }); Copy the code
Start -----------> end --------------> Network dataCopy the code
Exceptions during execution
getNetData().then((value) { // Support succeeded here print(value); }).catchError((error) { // Execution failed up to this point print(error); }); Copy the code
Common methods
-
Future.whenComplete
Whether the execution succeeds or fails it ends up here
getNetData().then((value) { // Support succeeded here print(value); }).catchError((error) { // Execution failed up to this point print(error); }).whenComplete(() => print("Complete")); Copy the code
Can be used to do some close dialog box operations
-
Future.them chain call
// Return values can be followed in them, which will be returned in the next chained then call getNetData().then((value) { // Support succeeded here print(value); return "data1"; }).then((value) { print(value); return "data2"; }).then((value) { print(value); }).catchError((error) { // Execution failed up to this point print(error); }).whenComplete(() => print("Complete")); Copy the code
Network data data1 data2 completedCopy the code
-
Future.wait
If you want to wait until multiple asynchronous tasks have finished to do something, you can use future.wait
Future.wait([getNetData(), getNetData(), getNetData()]).then((value) { value.forEach((element) { print(element); }); }); Copy the code
Wait takes an array of type Future and executes then only after all the futuresof the array have been successfully executed
-
Future.delayed
The function is executed after a certain time delay
Future.delayed(Duration(seconds: 3), () { return "Message in three seconds."; }).then((value) { print(value); }); Copy the code
-
-
Async and await
Async: Refers to functions that are asynchronous. The defined function returns a Future object. Callbacks can be added using then
“Await” : a Future means to await the completion of an asynchronous task. After the async task is completed, the async task will go further. “await” must appear inside async
void main() { print("start ------ ----->"); getNetData().then((value) => print(value)); print("end -------------->"); } Future<String> getNetData() async { var result1 = await Future.delayed(Duration(seconds: 3), () { return "Network Data 1"; }); var result2 = await Future.delayed(Duration(seconds: 3), () { return "Network Data 2"; }); return result1 + "-- -- -- -- --" + result2; } Copy the code
In getNetData, take two results, concatenate them, and return them together. The return value is wrapped in a Futter, and you can get the results directly using them at the call point. The official document, the Flutter of actual combat, Dart asynchronous (https://juejin.cn/post/6844903942795558919#heading-11) under the # # let us > happy codeingCopy the code