Basic chapter of Flutter -- old driver uses a blog to help you quickly get familiar with Dart grammar

Copyright notice: This is the original article of the blogger. It can't be reproduced without the permission of the blogger. https://www.jianshu.com/p/3d927a7bf020

Please indicate the source of Reprint:
https://www.jianshu.com/p/3d927a7bf020
From AWeiLoveAndroid blog

Flutter series blog links ↓:

Tool installation:

Basic chapter of Flutter:

Flutter advanced level:

Dart grammar series blog link ↓:

Dart grammar Foundation:

Advanced Dart syntax:

[foreword] dart language is a necessary language when developing with the framework of fluent, which is a cross platform framework. A set of code can perfectly realize the two platforms of Android and ios. The adaptation is also very good. Dart language is very friendly, similar to java, and the learning cost is very low. So that's one of the reasons I recommend learning dart.

Starting from this article to explain the basic use of Dart language, I will launch several articles to explain in detail, hoping to help you quickly master Dart language.

Contents:

1, Notes
2, Keywords (56)
3, Variables and constants
4, Special data types
5, Operators
6, Control process statement
7, Abnormal





The code of this article is published synchronously in Github:
https://github.com/AweiLoveAndroid/Flutter-learning/tree/master/projects/dart_demo

How to run the code?

If you use IDEA or Android Studio:

Open IDEA or Android Studio, create a new Flutter project, and then run my code in the test directory; or write your own dart file in it, and then right-click run to run it. (Note: you need to connect a mobile phone or simulator).

If you use vscode:

Open vscode and run it in the menu bar (make sure there is only one dart file, otherwise it's embarrassing that the running file is not what you want. Vscode can also set which file runs by default, but novices don't recommend setting it, which is troublesome. Because you want the fastest results, only one dart file is recommended.

1, Notes

Dart's comments are divided into three types: single line comment, multi line comment, and document comment.

1. Single line comments start with / /. The Dart compiler ignores everything between / / and the end of the line.

For example: / / todo: to be completed

2. Multiline comments start with / * and end with * /. Content between / * and * / is ignored by the compiler (unless the comment is a document comment). Multiline comments can be nested.

For example: / * todo: to be completed*/

3. Document comments start with / / or / *. You can export documents through the dartdoc command.

Use of document comments, for example: / / / todo: to be completed

The document is exported as shown in the figure:

 

Export of documents

The exported results are in the / doc/api / folder of my project root path, as shown in the figure:

Exported results

Then the browser opens index.html You can see the document. As shown in the figure:

Local documents

2, Keywords (60)

5 context keywords (meaning only in a specific location. They are valid identifiers everywhere)

keyword - - -
async hide on show
sync - - -

Among them, the built-in flags are: (20)

keyword - - -
abstract as covariant defered
dynamic export external factory
Function get implements import
interface library mixin operator
part set static typedef

Dart's newly added and limited reserved words support asynchronous functions with the following keywords: (2)

keyword - - -
await yield    

33 reserved words (reserved words cannot be used as identifiers)

keyword - - -
assert break case catch
class const continue default
do else enum extends
false final finally for
if in is new
null rethrow return super
switch this throw true
try var void while
with - - -

Compared with java, Dart's unique keywords are: (27)

keyword - - -
as async await covariant
deferred dynamic export external
factory Function get hide
in is library mixin
on operator part rethrow
set show sync typedef
var with yield  

3, Variables and constants

(1) Variable declaration, you can use var, Object, or dynamic keywords.

Create variables and initialize variable instances:

 

var name = 'Zhang San' ;

Variable store reference.

    1. Use Object or dynamic keywords

 

dynamic name = 'Zhang San';

The called variable name contains a reference to the object whose String value is "Zhang San".
name infers that the variable's type is String, but you can change that type by specifying it.
If the Object is not limited to a single type (no explicit type), use the Object or dynamic keyword

 

Object name = 'Zhang San';
dynamic name = 'Li Si';
    1. Explicitly declare the type to be inferred

Such as String,int, etc.

 

//You can use String to display declaration String types
String name = 'Zhang San' ; //Replace var name = 'Zhang San';

There are many types of this type, which are described below.

(2) Default

The initial value of uninitialized variables is null (including numbers), so numbers and strings can call various methods.

 

//What is the initial value of the test number type?
int intDefaultValue;
// assert is a language built-in assertion function that is only valid in check mode
// During development, exceptions are thrown unless the condition is true. (if the assertion fails, the program will terminate immediately.)
assert(intDefaultValue == null);
print(intDefaultValue);//The printing result is null, proving that the initialization value of the numeric type is null

(3) Use of Final and Const

If you never plan to change a variable, use final or const instead of var or a type.
A final variable can only be set once; the Const variable is a compile time constant. (the Const variable is an implicit final. )
The top-level or class variables of final are initialized the first time they are used.

  • 1. Variables modified by final or const can be omitted.

 

//You can omit the String type declaration
final name1 = "Zhang San";
//final String name1 = "Zhang San";
    
const name2 = "Li Si";
//const String name2 = "Li Si";
  • 2. Variables decorated with final or const can no longer modify their values.

 

final name1 = "Zhang San";
// In this way, the compiler prompts: a final variable, can only be set once
// A final variable can only be set once.
//name1 = "zhangsan";
    
const name2 = "Li Si";

// In this way, the compiler prompts: Constant variables can't be assigned a value
// const constant cannot be assigned
// name2 = "lisi";
  • 3. Note: flnal or const cannot be used together with var

 

//If you write like this, you'll make a mistake
 //final var name1 = "Zhang San";
//const var name2 = "Li Si";
  • 4. Constant if class level, use static const

 

static const speed = 100;
  • 5. Constant operation

 

const speed = 100; //Speed (km/h)
const double distance = 2.5 * speed; // Distance = speed * time

final speed2 = 100; //Speed (km/h)
final double distance2 = 2.5 * speed2; // Distance = speed * time
  • 6. The const keyword is more than just declaring constant variables. You can also use it to create constant values and declare constructors that create constant values. Any variable can have a constant value.

 

// Note: [] creates an empty list collection
// const [] creates an empty, immutable list (EIL).
var varList = const []; // varList is currently an EIL
final finalList = const []; // finalList has always been EIL
const constList = const []; // constList is the EIL of a compile time constant

// You can change the value of non final, non const variables
// Even though it used to have const values
varList = ["haha"];

// You cannot change the value of a final or const variable
// In this way, the compiler prompts: a final variable, can only be set once
// finalList = ["haha"];
// In this way, the compiler prompts: Constant variables can't be assigned a value  
// constList = ["haha"];
  • 7. As long as any interpolation expression is a compile time constant that evaluates to null or a number, string or Boolean value, the literal string is a compile time constant. (the $expression and different data types will be explained later. )

 

// These are constant strings
const aConstNum = 0;
const aConstBool = true;
const aConstString = 'a constant string';

// These are not constant strings

var aNum = 0;
var aBool = true;
var aString = 'a string';
const aConstList = const [1, 2, 3];

const validConstString = '$aConstNum $aConstBool $aConstString';

//Const variables must be initialized with a constant value
// const constants must be initialized with a value of type conat.
// const invalidConstString = '$aNum $aBool $aString $aConstList';

4, Special data types

Dart supports the following special types:

numbers
strings
Boolean
lists list collection (also known as an array)
maps map set
Runs character (used to represent Unicode characters in a string)




(1) num number type

num is the parent class of number type, which has two subclasses, int and double.
Num types include basic operators such as +, -, / and *, bit operators such as > > defined in the int class. If num and its subclasses don't have what you're looking for, the math library might find it. For example, you will find abs(),ceil(), floor() and other methods.

(1) int type

Int is an integer. Int is a 64 bit binary complement integer by default. The value of int is not greater than 64 bits, depending on the platform. When compiled into JavaScript, integers are limited to valus and can be represented exactly with double precision floating-point values. The available integer values include all integers between - 253 and 253, as well as some larger integers. This includes integers greater than 2 ^ 63. As a result, the behavior of operators and methods in the int class sometimes differs between Dart VM and Dart code compiled into JavaScript. For example, when compiled into JavaScript, bitwise operators truncate their operands to 32-bit integers.
An example is as follows:

 

int intNum1 = 10 ;
print(intNum1);//The result is 10
int intNum2 = 0xDEADBEEF ;
print(intNum2);//The result is 3735928559

To determine how many bits an int value requires, bitLength can be used, for example:

 

// bitLength returns the minimum number of bits required to store this int integer
int a1 = 1; // Takes up 1 bit equivalent to the binary number 00000000 00000001
int a2 = 12; // Takes up 4 bit s equivalent to the binary number 00000000 000011100
int a3 = 123; // Takes up 7 bit s equivalent to the binary number 00000000 011111011
int a4 = 1234; // Takes up 11 bit s, equivalent to the binary digit 00000100 11010010
print('${a1.bitLength}'); //  1
print('${a2.bitLength}');  // 4
print('${a3.bitLength}'); // 7
print('${a4.bitLength}'); // 11

(2) double type

Dart's double is the 64 bit floating-point number specified in IEEE 754 standard. The maximum value of double is: 1.7976931348623157e+308. There is a constant maxfinish in the double class. We can get the maximum value of double through the statement print (double. Maxfinish).
If a number contains a decimal, it is a double type. An example is as follows:

 

double doubleNum1 = 1.1;
print(doubleNum1); //The result is 1.1
double doubleNum2 = 1.42e5;
print(doubleNum2); //The result is 142000.0

(3) New feature in Dart2.1: when the value of double is int, int will be automatically converted to double.

For example: double test = 12; / / the printing result is 12.0

(4) Dart2.1,int also has api to double.

For example:

 

int test = 10;
print(test.toDouble()); // The result is: 10.0

(5) Dart2.1,double also has api to int, which will remove all the decimal points.

For example:

 

double test2 = 15.1;
double test3 = 15.1234;
print(test2.toInt());// The result is 15
print(test3.toInt());// The result is 15

(2) String string type

String in Dart is a series of UTF-16 code units.

(1) You can use single or double quotes to create a string.

 

String str1 = 'Basic use of single quotation mark demo.';
String str2 = "Basic use of double quotation marks demo.";

(2) Quotation marks are nested in single quotation marks or double quotation marks.

Single quotation marks are nested in single quotation marks, or / / double quotation marks are nested in double quotation marks. You must precede them with a backslash.

 

// The single quotation mark must be preceded by a backslash
String str3 = 'Single quotes with single quotes inside it\'s,Must be preceded by a backslash.';
//Nested single quotation mark in double quotation mark (normal use)
String str4 = "Double quotes with single quotes it's.";
//Nested double quotes in single quotes (normal use)
String str5 = 'There are double quotation marks in single quotation marks,"hello world"';
//Double quotation marks are nested inside, and must be preceded by a backslash
String str6 = "There are double quotes inside the double quotes,\"hello world\"";

print(str3);// Double quotes with single quotes it's must be preceded by a backslash
print(str4);// Double quotes with single quotes it's
print(str5);// Single quotes with double quotes, hello world“
print(str6);//Double quotes with double quotes inside, "hello world"

(3) Space between adjacent strings:

In addition to single quotation mark nesting single quotation mark or double quotation mark nesting double quotation mark, no empty string is allowed, other situations can run.
An example is as follows:

 

This will report an error
//String blankStr1 = 'hello''''world';
//These two operate normally
String blankStr2 = 'hello'' ''world'; //Result: hello world
String blankStr3 = 'hello''_''world'; //Result: hello_world


// This will report an error
//String blankStr4 = "hello""""world";
//These two operate normally
String blankStr5 = "hello"" ""world"; //Result: hello world
String blankStr6 = "hello""_""world"; //Result: hello_world

There are double quotation marks in single quotation marks, and the mixed use is normal

 

String blankStr7 = 'hello""""world'; //Result: Hello "" world
String blankStr8 = 'hello"" ""world'; //Result: Hello "" world
String blankStr9 = 'hello""_""world'; //Result: hello""_""world

There is single quotation mark in double quotation mark, and mixed use is normal

 

String blankStr10 = "hello''''world"; //Result: Hello ''World
String blankStr11 = "hello'' ''world"; //Result: Hello ''World
String blankStr12 = "hello''_''world"; //Result: hello''_''world

(4) You can connect strings using adjacent string literals or the + operator:

  1. You can connect strings by writing adjacent strings together.

 

  String connectionStr1 =  'String connection''Even in''Line break.';
  print(connectionStr1);// String concatenation can even be done at line feed time.
  1. Use + to connect adjacent strings.

 

  String connectionStr2 =  'String connection'+ 'Even in'+ 'Line break.';
  print(connectionStr2);// String concatenation can even be done at line feed time.
  1. Use three quotes of single or double quotes:

 

String connectionStr3 = ''' 
  This is created in single quotes
  Multiline string.
  ''' ;
print(connectionStr3);
String connectionStr4 = 'this is created in double quotes
  Multiline string. """;
print(connectionStr4);

The output of print(connectionStr3) is as follows:

 

  This is created in single quotes
  Multiline string.

The output of print(connectionStr4) is as follows:

 

This is created in double quotes
  Multiline string.

(5) On the use of escape symbols

Declare the raw string (prefix r), precede the string with the character r, or precede the \ with a \,
The escape function of "\" can be avoided, which is particularly useful in regular expressions.

For example:

 

print(r"Line break:\n"); //The result is a line break: \ n
print("Line break:\\n"); //The result is a line break: \ n
print("Line break:\n");  //The result is a line break:

(6) You can get the contents of a String by using $, or you can put the value of an expression into a String by using ${expression}. When using ${expression}, you can use String splicing, or you can use String class or some methods in Object to get related String properties.

1. Use $+ string

 

var height = 48.0;
print('The height of the current title is $height'); //The height of the current title is 48.0

2. Using $+ strings and string concatenation

 

String name = "Zhang San";
print("$name"+"It's our department manager"); // Zhang San is our department manager

3. Here we use String splicing and toUpperCase() function in String class to change all letters to uppercase.

 

String replaceStr = 'Android Studio';
assert('You know?' +
'${replaceStr.toUpperCase()}'
+ 'What's the latest version?' ==
'You know? ANDROID STUDIO What's the latest version?'); 

Note: the = = operator tests whether two objects are equal. assert is an assertion. If the condition is true, continue. Otherwise, throw an exception and operate at the middle end.

(3) bool boolean type

Dart indicates that the type of Boolean value is called bool. It has two values, true and false, which are compile time constants.
Dart uses an explicit check value, and the type of check value is as follows:

 

  // Check if it is an empty string
  var emptyStr = '';
  assert(emptyStr.isEmpty);

  // Check if it is less than or equal to 0
  var numberStr = 0;
  assert(numberStr <= 0);  

  // Check if it is null
  var nullStr;
  assert(nullStr == null);

  // Check if it is NaN
  var value = 0 / 0;
  assert(value.isNaN);

assert is an assertion function in Dart language, which is only valid in Debug mode.
During development, exceptions are thrown unless the condition is true. (if the assertion fails, the program will terminate immediately.).

(4) The list collection, also known as an array

In Dart, arrays are List objects, so most people just call them lists.
Here is a simple List of darts:

Create a list of type int

 

List list = [10, 7, 23];
print(list);// Output results [10, 7, 23]

To create a list of const constants at compile time, an example is as follows:

 

List constantList = const[10,3,15];
print(constantList);// Output results [10, 3, 15]

matters needing attention:

1. You can directly print the list including the list elements, and the list is also an object. But java must traverse to print list. If java prints list directly, the result is address value.
2. Like java, the elements in the list must be of the same type. If they are inconsistent, an error will be reported.
3. Like java, the subscript of list starts from 0.

Dart's list set provides us with many APIs. For example, there are too many APIs to show one by one:

operation code meaning Output results
newly added list.add(1);print(list); Add the number 1 to the list, which is added to the end by default [10, 7, 23, 1]
remove list.remove(1);print(list); Remove number 1 [10, 7, 23]
insert list.insert(0, 5);print(list); Insert the number 5 where the index is 0 [5, 10, 7, 23]
Find the value of an index int value = list.indexOf(10);print(value); Find the index of 10 in the list 1
Determine whether the element contains bool result = list.contains(5);print(result); Find if the list contains the number 5 true

(5) map set

A map in Dart is an object that associates a key with a value. Keys and values can be objects of any type. Each key appears only once, but you can use the same value multiple times.

(1) Created by:

    1. Direct declaration, represented by {}, in which key and value are written, and each group of key value pairs is separated by commas.

 

Map companys = {'first': 'Alibaba', 'second': 'tencent', 'fifth': 'Baidu'};
print(companys);//Print results {first: Alibaba, second: Tencent, fifth: Baidu}
    1. First declare, then assign.

 

  Map companys1 = new Map();
  companys1['first'] = 'Alibaba';
  companys1['second'] = 'tencent';
  companys1['fifth'] = 'Baidu';
  print(companys1);
  //Print results {first: Alibaba, second: Tencent, fifth: Baidu}
    1. To create a map with const at compile time, add const before the map text:

 

final fruitConstantMap = const {2: 'apple',10: 'orange',18: 'banana'};
// Print results {second: Tencent, fifth: Baidu, 5: Huawei}

(2) Add elements. Format: variable name [key] = value, where key can be of different types.

 

//Add a new element, key is "5", value is "Huawei"
  companys[5] = 'Huawei';
  print(companys);//Print results {first: Alibaba, second: Tencent, fifth: Baidu, 5: Huawei}

(3) Modify the element. Format: variable name [key] = value

For example, change the value of the element whose key is first to alibaba

 

  companys['first'] = 'alibaba';
  print(companys);//Print results {first: alibaba, second: Tencent, fifth: Baidu, 5: Huawei}

(4) Query elements

 

  bool mapKey = companys.containsKey('second');
  bool mapValue = companys.containsValue('Baidu');
  print(mapKey); //Result: true
  print(mapValue); //Result: true

(5) Delete element. You can use the remove or clear methods of map.

 

  companys.remove('first');// Remove the element with key "first".
  print(companys);// Print results {second: Tencent, fifth: Baidu, 5: Huawei}

  companys.clear();// Clear the data for the map collection.
  print(companys);// Print result {}

(6) Summary of map set:

 

1. There are two ways to create a map.
2. If the key types of map are inconsistent, no error will be reported.
3. When you add elements, they will be added to the map one by one according to the order in which you add them, even if your key s are not continuous.
For example, the key is 1, 2, 4, which seems to have interval. In fact, when it is added to the map, it takes the form of {1:value,2:value,4:value}.
4. If the key of the added element is the English of a key in the map, it can also be added to the map,
For example, it can be 3 and key can be three.
5. The key in the map cannot be the same, but the value can be the same, and the value can be an empty string or null.

(6) Runs character (used to represent Unicode characters in a string)

Unicode defines unique values for each letter, number, and symbol used in all writing systems in the world.
Dart string is a sequence of UTF-16 code units, so it needs special syntax to express 32-bit Unicode value in string.
A common method for Unicode code points is \ uXXXX, where XXXX is a 4-digit hexadecimal value.

For example, the heart character () is \ u2665. To specify more than or less than four hex digits, place the value in braces. For example, the smiley emoticon is \ u{1f600}.

The String class has several properties that can be used to extract character information. The codeUnitAt and codeUnit properties return 16 bit code units.
The following example illustrates the relationship between symbols, 16 bit code units, and 32-bit code points.

 

var clapping = '\u{1f44f}';
print(clapping);
print(clapping.codeUnits);
print(clapping.runes.toList());

//Use String. fromCharCodes to display character graphics 
Runes input = new Runes(
        '\u2665  \u{1f605}  \u{1f60e}  \u{1f47b}  \u{1f596}  \u{1f44d}');
print(new String.fromCharCodes(input));

5, Operators

Operators are common in every language. Dart's operators are shown in the following table:

I'm not going to explain the usage of each operator in detail here. I'm going to talk about some representative and characteristic operator related usages in Dart.

(1) ?. Like. But the leftmost operand can be empty.

For example: Test?. funds select the property funds from the expression Test, unless Test is empty (when Test is empty, the value of Test?. funds is empty).

 

class Test {
  static int funs = 5;

  Test() {
    print('Constructor Test');
  }
  static fun() {
    print('Test fun function');
  }
}
void main(){
  print(Test?.funs); // Print 5
}

(2) ... concatenated symbols

Cascading symbols.. allow you to perform a series of operations on the same object. In addition to function calls, you can access fields on the same object. In fact, it is equivalent to java chain call.
For example:

 

String s = (new StringBuffer()
        ..write('test1 ')
        ..write('test2 ')
        ..write('test3 ')
        ..write('test4 ')
        ..write('test5'))
      .toString();
print(s); // test1 test2 test3 test4 test5

(3) A form of the trinary operator.

Expr1?? expr2 means if expr1 is not empty, its value will be returned; otherwise, the value of expr2 will be returned.

 

//Ordinary ternary operator
int a = 10;
var values = a > 5 ? a : 0;
//?? Operator
print('a ??=3 : ${a ??= 3}');  // 3

(4) The division of ~ / returns an integer result, which is actually the quotient.

Primary school students have learned: dividend ÷ divisor = quotient... Remainder, in dart, A ~/ B = C, this C is quotient, this statement is equivalent to A / B = C in Java. Dart is different from Java in that if the A / B = D statement is used in dart, the result is the real result. An example is as follows:

 

  var result1 = 15/7;
  print(result1); // The result is: 2.142857
  var result2 = 15~/7;
  print(result2); // The result is: 2

By the way, in Dart, a% B = E, this E is the remainder, and the% symbol indicates modulo, for example:

 

 var result3 = 15%7;
  print(result3); // The result is: 1

(5) as, is and is!

as judgment belongs to a certain type
is true if the object has the specified type
is! false if the object has the specified type

For example:

 

class Test {
  static int funs = 5;

  Test() {
    print('Constructor Test');
  }
  static fun() {
    print('Test fun function');
  }
}

class Test2 extends Test {
  Test2() {
    print('Constructor Test2');
  }
  void fun() {
    print('Test2 fun function');
  }
}

void main(){
  print(test2 is Test);  // true
  print(test is! Test2);  // true

  (test2 as Test2).fun();  // Test2 fun function
  // amount to
  // if (test2 is Test) {
  //   test2.fun();
  // }

6, Control process statement

The control process statements are similar to the Java language. There are these statements:

(1) if else

 

If (conditional statement){
    Content body
}else{
Content body
}

(2) for loop

1. Simple for loop

 

For (initial value; judgment condition; statement after loop){
    Content body
}

For example:

 

for(int i=0;i<10;i++){
    print(i);
}

You can also get the value of the index through the closure inside the for loop.

 

var array = [];
for(var i=0;i<10;i++){
    array.add(()=> print(i));
}

2. Using foreach loop, generally List and Set can use foreach to traverse elements.

If the object to be iterated is iterative, or you don't want to know the current number of iterations, you can use the foreach() method.

 

var numbers = [1,2,3,4,5,6,7,8,9];
numbers.foreach((number)=> print(number));

3. Use for in loop. Generally, List and Set use for in to traverse elements.

 

var list = [1,2,3];
for(var data in list){
    print(data);
}

4. In DART's for loop, you can use the tag: (a more distinctive place)

Dart's tag: a tag is an identifier followed by a colon. A tagged statement is a statement prefixed with the tag L. The case clause with label is the case clause in the switch statement with label l prefix. The only purpose of tags is to provide objects for "break" and "continue" declarations.
Most of this functionality is similar to other languages, so most of the following may be familiar to readers. Dart's switch statement is unique in its handling of continue, so it takes a little time to read and get familiar with this part.

  • 1. Loops

Tags are most commonly used as break and continue inner loops. Suppose you have nested loops and want to jump to break or continue to external loops. This is not possible (easily) without tags.

The following example uses the continue tag name to jump directly from the inner loop to the next loop of the outer loop:

 

// Returns the internal list (positive integer) with the minimum sum.
/// Returns the inner list (of positive integers) with the smallest sum.
List<int> smallestSumList(List<List<int>> lists) {
  var smallestSum = 0xFFFFFFFF; //The sum of known list s is small.
  var smallestList = null;
  outer: // This is the sign
  for (var innerList in lists) {
    var sum = 0;
    for (var element in innerList) {
      assert(element >= 0);
      sum += element;
      // There is no need to continue iterating on the inner list. The sum of it is too high.
      if (sum > smallestSum) continue outer; // continue to jump out to the marker
    }
    smallestSum = sum;
    smallestList = innerList;
  }
  return smallestList;
}

This function runs in all list s, but stops accumulating variables as long as the sum is too high.

Similarly, you can use break to jump out of an external loop:

 

// Calculate the first non empty list
List<int> firstListWithNullValueList(List<List<int>> lists) {
  var firstListWithNullValues = null;
  outer:
  for (var innerList in lists) {
    for (var element in innerList) {
      if (element == null) {
        firstListWithNullValues = innerList;
        break outer;  // break returns to the tag
      }
    }
  }
  // Continue the normal workflow now
  if (firstListWithNullValues != null) {
    // ...
  }
  return firstListWithNullValues;
}
  • 2. Jump out of code block

Tags can also be used to jump out of code blocks. Suppose we want to deal with error conditions uniformly, but there are multiple conditions (possibly deep nesting) to reveal the error. Tags can help build this code.

 

void doSomethingWithA(A a) {
  errorChecks: {
    if (a.hasEntries) {
      for (var entry in a.entries) {
        if (entry is Bad) break errorChecks;   // Jump out of code block
      }
    }
    if (a.hasB) {
      var b = new A.b();
      if (b.inSomeBadState()) break errorChecks;  // Jump out of code block
    }
    // Some of them look normal
    use(a);
    return;
  }
  // In case of error, execute the following code:
  print("something bad happened");
}

class A{
  bool hasEntries = false;
  bool hasB = true;
  List<Bad> entries = [new Bad2(),new Bad2()];
  A.b(){

  }

  bool inSomeBadState(){
    return false;
  }
  
}

void use(A a){}

abstract class Bad{}
class Bad1 extends Bad{}
class Bad2 extends Bad{}

The use of the break instruction on the code block causes Dart to continue executing the statements after the block. From a certain point of view, it is a structured goto, which only allows you to jump to the less nested position after the current instruction.

Although declaration tags are most useful in code blocks, they can be used in every statement.
For example, foo: break foo; is a valid declaration.

Note that the loop above continue can be implemented by wrapping the body of the loop into a tagged block of code and using break.
In other words, the following two cycles are equivalent:

 

//The following two descriptions are equivalent:

// Using continue
for (int i = 0; i < 10; i++) {
  if (i.isEven) continue;
  print(i);
}

// Use break
for (int i = 0; i < 10; i++) {
  labels: {
    // isEven returns true if and only if the integer is even
    if (i.isEven) break labels;
    print(i);
  }
}
  • 3. Label in switch

Tags can also be used inside a switch.
Tags in Switch allow continue to use other case clauses. In the simplest form, this can be used as a way to implement the next clause:

 

void switchExample(int foo) {
  switch (foo) {
    case 0:
      print("foo is 0");
      break;
    case 1:
      print("foo is 1");
      continue shared; // Continue is used in a clause marked shared
    shared:
    case 2:
      print("foo is either 1 or 2");
      break;
  }
}

Interestingly, Dart does not require that the target clause of continue be the one after the current case clause.
Any case clause marked is a valid target. This means that Dart's switch statement is actually a state machine.

The following example demonstrates this abuse, where the entire switch is actually just a state machine.

 

void main() {
  runDog();
}

void runDog() {
  int age = 0;
  int hungry = 0;
  int tired = 0;

  bool seesSquirrel() => new Random().nextDouble() < 0.1;
  bool seesMailman() => new Random().nextDouble() < 0.1;

  switch (1) {
    start:
    case 0:
      print("dog Method started");
      print('case 0 ==> age: $age');
      print('case 0 ==> hungry: $hungry');
      print('case 0 ==> tired: $tired');
      continue doDogThings;

    sleep:
    case 1:
      print("sleeping");
      tired = 0;
      age++;
      if (age > 20) break;
      print('case 1 ==> age: $age');
      print('case 1 ==> hungry: $hungry');
      print('case 1 ==> tired: $tired');
      continue doDogThings;

    doDogThings:
    case 2:  
      if (hungry > 2) continue eat;
      if (tired > 3) continue sleep;
      if (seesSquirrel()) continue chase;
      if (seesMailman()) continue bark;
      print('case 2 ==> age: $age');
      print('case 2 ==> hungry: $hungry');
      print('case 2 ==> tired: $tired');
      continue play;

    chase:
    case 3:  
      print("chasing");
      hungry++;
      tired++;
      print('case 3 ==> age: $age');
      print('case 3 ==> hungry: $hungry');
      print('case 3 ==> tired: $tired');
      continue doDogThings;

    eat:
    case 4:  
      print("eating");
      hungry = 0;
      print('case 4 ==> age: $age');
      print('case 4 ==> hungry: $hungry');
      print('case 4 ==> tired: $tired');
      continue doDogThings;

    bark:
    case 5: 
      print("barking");
      tired++;
      print('case 5 ==> age: $age');
      print('case 5 ==> hungry: $hungry');
      print('case 5 ==> tired: $tired');
      continue doDogThings;

    play:
    case 6: 
      print("playing");
      tired++;
      hungry++;
      print('case 6 ==> age: $age');
      print('case 6 ==> hungry: $hungry');
      print('case 6 ==> tired: $tired');
      continue doDogThings;
  }
}

This function jumps from one switch clause to another, simulating the life of a dog.
In Dart, tags are only allowed in case clauses, so I have to add some lines that case will never reach.

This feature is cool, but rarely used. Because our compiler adds complexity, we often discuss its deletion. So far, it has survived our review, but we may eventually simplify our specification and let users add a while(true) loop (with tags) themselves. The example of this dog can be rewritten as follows:

 

var state = 0;
loop:
while (true)
  switch (state) {
    case 0:
      print("dog has started");
      state = 2; continue;

    case 1:  // sleep.
      print("sleeping");
      tired = 0;
      age++;
      // The inevitable... :(
      if (age > 20) break loop;  // Jump out of the loop
      // Wake up and do dog things.
      state = 2; continue;
    
    case 2:  // doDogThings.
      if (hungry > 2) { state = 4; continue; }
      if (tired > 3) { state = 1; continue; }
      if (seesSquirrel()) { state = 3; continue; }
      ...

If the state value is named constant, it will be as readable as the original version, but no switch statement is required to support the state machine.

(3) While and do while

 

While (judgment condition){
    Content body
}

 

do{
Content body
 }While (judgment condition);

 

while(a>5){
    print(a);
}

 

do{
print(a);
} while(a>5);

(4) break continue

break stop cycle

 

while(a>5){
  if(b>5){
  print(a);
    break;
  }
}

continue jumps to the next loop

 

while(a>5){
  if(b<10){
  print(b);
    continue;
  }
}

If you use Iterable (list or set), you can use this method:

 

// The first is to meet the condition and enter the second is foreach traversal
arrays
  .when((c)=>c.counts >=5)
  .foreach((c)=>c.next());

(5) switch case

Compare integer, string, compile time constant use = =. The comparison object must be an instance of the same class (not an instance of its subclass), and the class cannot override = =. Enumeration types can also be run in switch.
Each non empty case clause ends with a break, or in another way: continue,throw, or return.

 

var command = 'OPEN';
switch (command) {
  case 'CLOSED':
    executeClosed();
    break;
  case 'PENDING':
    executePending();
    break;
  case 'APPROVED':
    executeApproved();
    break;
  case 'DENIED':
    executeDenied();
    break;
  case 'OPEN':
    executeOpen();
    break;
  default:
    executeUnknown();
}

(6) assert

If the Boolean condition is false, the assert statement is used to interrupt normal execution. For example:

 

// Make sure the variable has a non null value 
assert(text != null);
// Make sure the value is less than 100
assert(number < 100);
// Make sure this is an https URL
assert(urlString.startsWith('https'));

To attach a message to an assertion, add a string as the second parameter.

 

assert(urlString.startsWith('https'),'URL ($urlString) should start with "https".');

The first parameter to assert in the above example can be any expression that resolves to a Boolean value. If the value of the expression is true, the assertion succeeds and execution continues. If false, the assertion fails and an exception is thrown

7, Abnormal

Dart code can throw and catch exceptions. Exception is an error indicating that an unexpected event occurred. If the exception is not caught, the isolate that threw the exception is paused, and usually the isolate and its program are terminated.

All exceptions to Dart are unchecked compared to Java. Methods do not declare the exceptions they may throw, and you do not need to catch any exceptions.

Dart provides Exception and Error types, as well as many predefined subtypes. Of course, you can define your own exceptions. However, the dart program can throw any non null object as an Exception (not just Exception and Error objects).

(1) throw

Here is an example of throwing or throwing an exception:

 

throw FormatException('Expected at least 1 section');

You can also throw any object, for example: throw 'is not in the correct format!';
Error or Exception types are usually thrown in development.

Because throwing an exception is an expression, you can throw an exception in the = > statement and anywhere else that allows the expression:

 

void distanceTo(Point other) => throw UnimplementedError();   

(2) try catch

Catching or catching an exception prevents exception delivery (unless you rethrow the exception). Catching an exception gives you the opportunity to handle it:

 

try {
    breedMoreLlamas();
} on OutOfLlamasException {
    buyMoreLlamas();
}

To handle code that can throw multiple types of exceptions, you can specify multiple catch clauses. The first catch clause that matches the type of the thrown object handles the exception. If the catch clause does not specify a type, it can handle throw objects of any type.
You can use on or catch or both. An exception type needs to be specified when using on. When using catch, your exception handler needs an exception object.
Example:

 

try {
  breedMoreLlamas();
} on OutOfLlamasException {
  // A specific exception
  buyMoreLlamas();
} on Exception catch (e) {
  // Anything else that is an exception
  print('Unknown exception: $e');
} catch (e) {
  // No specified type, handles all
  print('Something really unknown: $e');
}

You can specify one or two parameters, catch(). The first is the exception thrown, and the second is the stack trace (StackTrace object).
Example:

 

try {
  // ···
} on Exception catch (e) {
  print('Exception details:\n $e');
} catch (e, s) {
  print('Exception details:\n $e');
  print('Stack trace:\n $s');
}

To partially handle an exception while allowing it to pass, use the rethrow keyword.
Example:

 

void misbehave() {
  try {
    dynamic foo = true;
    print(foo++); // Runtime exception
  } catch (e) {
    print('misbehave() partially handled ${e.runtimeType}.');
    rethrow; // Allow the caller to view the exception
  }
}

void main() {
  try {
    misbehave();
  } catch (e) {
    print('main() finished handling ${e.runtimeType}.');
  }
}

(3) finally

To ensure that some code runs, whether or not an exception is thrown, use the finally clause. If no catch clause matches the exception, pass the exception after the finally clause runs.
Example:

 

try {
  breedMoreLlamas();
} finally {
  // This code will execute even if an exception is thrown
  cleanLlamaStalls();
}
//The finally clause runs after any matching catch clause:
try {
  breedMoreLlamas();
} catch (e) {
    // Exception will be handled first
  print('Error: $e'); 
} finally {
  // Then execute the statement
  cleanLlamaStalls(); 
}



By AWeiLoveAndroid
Link: https://www.jianshu.com/p/3d927a7bf020
Source: Jianshu
The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.




Tags: Java Android less Javascript

Posted on Sun, 07 Jun 2020 06:35:46 -0400 by linoukus