Getting started with dart

Time:2020-11-27

Getting started with dart

Recently,flutterThe heat is rising. The main development language of fluent application isdartSo, if you want to know, you have to practicedart.

Dart is a programming language developed by Google, which can be used to develop mobile applications, desktop applications, H5 applications and back-end services.

This article will briefly introducedartThis paper introduces the language features, basic syntax, and practical skills in daily development, such as how to request data, how to handle asynchronous, how to serialize and deserialize JSON.

The article is relatively long, familiar with some of you can quickly browse, the end of the article also gives a small welfare, for your reference. Excuse me for the omissions and correct the mistakes.


Linguistic features

object-oriented

Dart is a pure object-oriented language, in which everything is object.

  • Functions are also objects. Functions can be assigned to variables, as parameters or return values of functions
  • The underlying type is an object, and the literal value is also an object. For example, it can be used like the following
1.toString();

Supports top level functions and variables

Unlike Java, Java’s variables and methods can only be in the class, while dart can have methods and variables that are not in the class.

With process oriented language features, such as C.

Both strong type and weak type are supported

In dart, you can explicitly specify the type of the variable, or you can infer the type by dart without specifying the type. If the type is specified, the compiler can do static type checking.

In terms of type, dart has the characteristics of both weakly typed languages (like JS) and strongly typed (like Java).

It has the characteristics of both interpretative language and compiler language

For the development of web applications: dart will be translated into JS

For app, server and desktop applications:

  • Dart provides development mode, which is interpreted and executed by VM, supports hot update, and has the characteristics of interpretive language
  • It also provides a production mode, which can be executed by compiling machine code, and has the characteristics of compiled language

Summary

Dart seems to want to integrate the features of many mainstream languages, and the shadow of multiple languages can be seen in dart.

Basic grammar

Program entry

The program execution entry of dart is the main function, which is very similar to C. The main function is a top-level function.

The return value is usually void. If it is written as int or double, it will not report an error, but it is meaningless.

void main() {
  print('Hello, World!');
}

variable and constant

  • Variables or constants in dart must be defined before use
  • Uninitialized variables and constants default to null

variable

  1. Var variable name [= value];
void main() {
  var var1 = '1';
  print(var1); // 1
  //VAR1 = 1; this is an error. Declaration and initialization will infer the type and cannot assign values of other types
  var var2;
  print(var2); // null
  var2 = 2;
  print(var2); // 2
  var2 = '3';
  Print (var2); // 3 is correct. If you do not assign a value when you declare it, it is equivalent to declaring a dynamic variable
}
  1. Data type variable name [= value];

In this way, variable types can be explicitly declared for some static checking.

void main() {
  //Declare and initialize
  int var1 = 1;
  print(var1); // 1

  //Initialization and declaration
  int var2;
  var2 = 1;
  print(var2); // 1

//Var2 ='1 '; this is an error and the type does not match
}
  1. Dynamic variable name [= value]

This dynamic means dynamic type. This variable can assign any type of value to it

void main() {
  dynamic var1 = 1;
  VAR1 ='2 '; // dynamic type can be assigned any type of value
  print(var1); // 2
}

constant

  1. Final constant name = value

Its value is determined at run time and can be used as a normal member variable of a class

  1. Const [data type] constant name = value

Its value must be determined at compile time. It can only be used as a static member variable of a class, not as a normal member variable

class User {
  final int var1=1;
  static const int var2=2;
//Const int var3 = 3; error, cannot be a normal member variable of a class
}

void main() {
  int var1 = 1;
  int var2 = 2;
  final int const1 = 1;
  const int const2 = 2;
//Const1 = 2; error, cannot be changed again
//Const2 = 1; error, cannot be changed again

//Final int const3; error, must be initialized
//Const int const4; error, must be initialized
  final int const5 = var1 + var2;
//Const int cont6 = VAR1 + var2; error, value must be determined at compile time
}

data type

  1. num、int、double
  • Both int and double are num types
  • It’s all 8 bytes
  • Is an object with some methods and properties
  • There are no unsigned types
void main() {
  int int1 = 1;
  double double1 = 1.3;
  num num1 = 2.0;
//The following raises a runtime exception
//  int1 = num1;
//  print(int1);
  print(int1.toString()); // 1
  print(int1.isEven); // false
  print(int1.floor()); // 1
  print(int1.isNaN); // false

  print(double1.toString()); // 1.3
  print(double1.floor()); // 1
  print(double1.isNaN); // false
}
  1. String

Literal representation

  • Single line literal value representation:’xx ‘or’ XX ‘
  • Multi line literal representation: ”’xxx’ ” or ‘”xxx'”
  • Ignore interpreter: r’xxnxx ‘
void main() {
  String str1 = 'str1';
  print(str1); // str1
  String str2 = "str2";
  print(str2); // str2
  String str3 = '''a
b
c
  ''';
  print(str3);
//  a
//  b
//  c

  String str4 = "a\nb";
  String str5 = r"a\nb";

  print(str4);
//  a
//  b
  print(str5); // a\nb
}

Common properties and methods

The properties and methods of string are similar to those of other languages. Here are some common methods and properties

void main() {
  String STR1: "my motherland and I";
  String STR2 = ", can not be split for a moment";
  String str3 = str1 + str2;

  print(str1.length); // 6
  Print (STR1. Substring (2)); // my country
  List<String> list = str3.split(",");
  Print (list); // [my motherland and I can't be separated for a moment]
  Print (STR1. Startswith ("me"); // true
  Print (STR1. Indexof ("me"); // 0
  Print (STR1. LastIndexOf ("me"); // 2
  Print (STR1. Replaceall ("I", "you"); // you and your motherland
  print("a".compareTo("b")); // -1
  Print (STR1. Contains ('motherland '); // true
}
  1. bool

Boolean value. The literal value can only be true or false, not other

void main() {
  bool bool1 = true;
  print(bool1); // true
}
  1. List

Similar to the array in JS, variable length.

void main() {
  List<int> list = [1, 3, 4];
  print(list.length); // 3
  print(list); // [1, 3, 4]
  list.add(5);
  print(list); // [1, 3, 4, 5]

  list.addAll([6, 7]);
  print(list); // [1, 3, 4, 5, 6, 7]
  print(list.removeLast()); // 7
  print(list); // [1, 3, 4, 5, 6]
  list.removeAt(0);
  print(list); // [3, 4, 5, 6]
  list.remove(3);
  print(list); // [4, 5, 6]
  list.sort((item1, item2) {
    return item2 - item1;
  });
  print(list); // [6, 5, 4]
  list.forEach((item) {
    print(item);
  });
// 6
// 5
// 4
  print(list.indexOf(4)); // 2
  list.clear();
  print(list); // []
}
  1. Set

Represents a set. There are no duplicate values. Adding complex values will not report an error, but it will not go in and out of order.

void main() {
  Set<int> set = {1, 3, 3, 4};
  print(set); // {1, 3, 4}
  set.add(9);
  print(set); // {1, 3, 4, 9}
  print(set.contains(3)); // true
  print(set.length); // 4
  set.remove(3);
  print(set); // {1, 4, 9}
  print(set.isEmpty); // true
}
  1. Map

Represents K-V structure data, and the key cannot be duplicate.

void main() {
  Map<String, int> map = {
    "a": 1,
    "b": 2,
  };

  print(map); // {a: 1, b: 2}
  map['c'] = 3;
  print(map); // {a: 1, b: 2, c: 3}
  map.remove('a');
  print(map); // {b: 2, c: 3}
  print(map.containsKey('a')); // false
  print(map.length); // 2
  print(map.containsValue(3)); // true
}
  1. enum

Enumeration is a special class, which is not included in the basic type in the official documents. It is put here for the convenience of understanding.

enum Color {
  red,
  blue,
  yellow,
}

void main() {
  Color c = Color.red;
  print(Color.blue); // Color.blue
  print(Color.values); // [Color.red, Color.blue, Color.yellow]
  print(c); // Color.red
}

Data type conversion

  • Java has automatic type conversion mechanism, for example, it can automatically convert int type to double; in dart, type mismatch must be forced conversion, and there is no automatic type conversion
  • Conversion of other types to strings or numbers to toxxx() methods
  • String to number uses the parse() method of the number class (int, double, Num)
void main() {
  int int1 = 1;
  //Error, unable to convert automatically
  // double double1= int1;

  //Conversion between double and int
  double double1 = int1.toDouble();
  int1 = double1.toInt();

  //Num is the parent type of int and double, which can be converted directly
  num num1 = double1;
  num1 = int1;

  //Conversion between string and double
  String str1 = double1.toString();
  double1 = double.parse(str1);

  //Conversion between string and int
  String str2 = int1.toString();
  int1 = int.parse(str2);

  //Map, set, list can be converted to string by using its toString method
  Map map = {"a": 1, "b": 2};
  List list = [1, 2, 3];
  Set set = {1, 2, 3};

  String str3 = map.toString();
  list.toString();
  set.toString();
}

Operator

The operators are basically the same as other languages. Here are a few special, other simple lists.

  1. Arithmetic operator

+、-、*、/、%、++、–

What’s more special is that~/, denotes an integral division

void main() {
  int int1 = 3;
  print(int1 ~/ 2); // 1
}
  1. Comparison operator

==、!=、>、<、<=、>=

  1. Assignment Operators

=, – =, ~ / = etc

What’s more special is thatVariable name?? = valueIf the left variable is null, the value is assigned; otherwise, it is not assigned

void main() {
  int a;
  a ??= 1;
  print(a); // 1

  int b = 2;
  b ??= 1;
  print(b); // 2
}
  1. Logical operator

!、||、&&

  1. Bitwise Operators

&、|、^、~expr、<<、>>

  1. Conditional expression

condition ? expr1 : expr2

  1. Class transport operator

This is a special operator, similar to the continuous. Operation in jQuery. The last operation still returns the current object, so you can continue to call its methods. Most languages don’t have this kind of operation.

class User {
  say() {
    print("say");
  }

  run() {
    print("run");
  }
}

void main() {
  User user = User();
  user..say()..run();
  // say
  // run
}
  1. Class Operators

This is a special operator, used to determine the type and strong conversion, similar to Java(User) instancesuch

  1. instance as className

It is used to convert a type to another type. The parent-child relationship must be satisfied. Otherwise, an error is reported.

  1. import ‘xxx’ as variable;

It is used to specify the alias name of the import library, which is equivalent to hanging the exported items from the library to a map, which can solve the problem of duplicate names.

  1. instance is classNmae

Used to determine whether an object is an instance of a class

  1. instance is! classNmae

The result of is is is negative

import ' dart:math 'as math; // here, the alias name is specified with as when importing the library

class Person {
  String name;

  Person();

  say() {
    print("person say $name");
  }
}

class User extends Person {
  String password;

  User(this.password);

  run() {
    print("user run");
  }
}

void main() {
  print( math.max (4, 5)); // specifies the library call of the alias
  User u = User("password");
  print(u is User); // true
  u.name = "name";
  u.run(); // user run
  Person P = u as person; // use as to force the child type to the parent type
  print(p is User); // true
  print(p is Person); // true
  print(p is List); // fasle
  p.say(); // person say name
  //P.run(); // error. It has been converted to person and cannot call user's method any more
}

Process control statement

Process control is the same as other languages. Here is a brief list

  • if .. else if..else
  • for
  • while、do..while
  • break、continue
  • switch .. case
  • assert

Assert is an assertion to judge whether an expression is true or false. If it is false, an exception will be thrown

modularization

Dart supports modular programming. It can import dart built-in library, other three-party libraries, and split its own code into different modules.

  1. Import
  • Import built in Library
import "dart:math";
  • Import tripartite Library

Need to be in project description file pubspec.yaml (similar to JS package.json Or Java pom.xml )Declare the library you want to depend on, then install it, and finally import it.

pubspec.yaml

dependencies:
  http: ^0.12.0+2

install

pub get

Import

import 'package:http/http.dart';
  • Import local file

After importing a local file, you can use the classes, variables, functions, etc. defined in it

import '../common/Utils.dart';
  • Specify alias on import

It is equivalent to hanging the exported objects of a library to an object, which can solve the problem of duplicate names (mentioned in as above)

import 'package:http/http.dart' as http;
  • Conditional import

You can import only the specified content or not import some content

import 'package:lib1/lib1.dart' show foo;
import 'package:lib2/lib2.dart' hide foo;
  • Import dynamically or load on demand

You can import dependencies at run time, which is similar to webpack on-demand loading for web applications.

  1. Create Library

There are many contents, which are omitted here. The author has not studied them yet and can be referred toOfficial website

  1. Introduction to dart built-in Library
  • dart:core

Dart core library, imported by default, similar to Java java.lang Bag. Provide built-in data types, etc.

  • dart:async

Asynchronous support library, the famous future is here.

  • dart:math

Complex mathematical calculation correlation

  • dart:convert

JSON serialization, deserialization, character set conversion.

  • dart:html

Web application related API

  • dart:io

IO related. The httpclient related to the request is here

function

  • Functions can be at the top level, that is, they do not belong to any class
  • A function can be a member method of a class
  • There can be a return value or no return value
  • Functions are objects that can be assigned to variables, as parameters or as return values
  • Parameters can be common positional parameters or named parameters. When passing named parameters, it is not necessary to consider the order. Most languages do not have named parameters. It is said that they are borrowed from OC
  • Arrow functions can only be used for functions with one statement
  • You can use typedef to define specific function types
  • Function parameters can specify default values
//Function with no return value
import 'package:flutter/foundation.dart';

void printInfo(String name, int age) {
  print('$name:$age');
}

//Functions with return values
String getInfo(String name, int age) {
  return '$name:$age';
}

//Functions are passed as arguments
void excuteFn(var function, String name, int age) {
  function(name, age);
}

//Returns a function
Function getPrintInfoFn(int age) {
  return (String name) {
    print('$name:$age');
  };
}

//There is only one statement in the function body, and arrow functions can be used
void printInfo2(String name, int age) => print('$name:$age');

//You can use named parameters
void printInfo3({String name, int age}) {
  print('$name:$age');
}

//Mix positional and named parameters to specify default values
void printInfo4(String name, { int age}) {
  print('$name:$age');
}

//Define a function type
typedef PrintFn = void Function(String name, int age);

//Passing a function of a specific type as an argument
void excuteFn2(PrintFn function, String name, int age) {
  function(name, age);
}

class User {
  //Function as a member method of a class
  say() {
    print("hello");
  }
}

void main() {
  Printinfo ("Zhang San", 18);
  Print (getinfo ('li Si ', 18));
  User user = User();
  user.say();
  Ex cutefn (printinfo, "Wang Wu", 18);
  Function fn1 = getPrintInfoFn(19);
  FN1 ("Xiaoming");
  FN1 (floret);
  Printinfo ("Xiaozhang", 18);
  Printinfo2 ('xiao Li ', 20);
  Printinfo3 (Name: "Xiaohua", age: 21); // named parameter function call method
  printInfo4("AA");
  printInfo4("aa", age: 30);
  Ex cutefn2 (printinfo, "Wang Wu", 18);
}

notes

  1. Single-Line Comments
//I'm a line of notes
  1. multiline comment
/**
 *Multiline comment
 *Multiline comment
*/
  1. Documentation Comments
///Document notes
///Document notes

object-oriented

Definition and composition of class

Classes are defined using the class keyword

A class can consist of the following parts:

  • Common member variable
  • Static member variable
  • General method
  • Static method
  • Constructor. If it is not declared, it will be constructed with or without parameters by default
  • Named constructor
  • Set, get method

explain

  • Overloading is not supported
  • Static members can be accessed without instantiation and can only be accessed by class name, unlike Java, which can access static member variables through instances
  • This cannot be used in static member methods, and only static member variables can be accessed
  • If set is not written, the get method will have default set and get methods
  • Do not support public, private and other access modifiers, general convention_ The variable at the beginning is private, but it is only a convention and can be accessed in practice
//Use the class keyword to define a class
class Rectangle {
  //Two member variables, variable name plus_ The representation is private, only a convention, and the essence can still be accessed
  double _height;
  double _width;

  //Static member variables can be accessed by type without instantiation
  Static string name = rectangle;

  Rectangle(double width, double height) {
    this._width = width;
    this._height = height;
  }

  //If the unnamed constructor only assigns values to the member variables, it can be written in this way, which is equivalent to the above method
  // Rectangle(this._width, this._height);

  //Named construction method
  Rectangle.fromMap(Map<String, double> map) {
    this._width = map['width'];
    this._height = map['height'];
  }

  static String getName() {
//    return this._ height.toString (); error, static member methods cannot use this and non static member variables
    return name;
  }

  double getArea() {
    return _height * _width;
  }
  //Double getarea already exists. It cannot be written in this way. Overloading is not supported
  // double getArea(double width, double height) {
  //
  // }

  //Get set method
  double get width {
    Print ("call get width");
    return _width;
  }

  set width(double value) {
    Print ("call set width");
    _width = value;
  }

  double get height => _height;

  set height(double value) {
    _height = value;
  }
}

void main() {
  print(Rectangle.name);
  print(Rectangle.getName());
  Rectangle rectangle = Rectangle.fromMap({'width': 10, 'height': 20});
  print(rectangle.getArea());
  rectangle.width = 1;
  print(rectangle.width);
}

inherit

main points:

  • Use the extends keyword
  • Only single inheritance is supported
  • The subclass can obtain the common member method and the common member variable of the parent class, but cannot get the static member, and the constructor cannot inherit
  • You can override the methods of the parent class, and you can use super to access the parent class
  • If the parent class does not have a parameter free construction, the child class must display the structure calling the parent class, otherwise an error is reported
//Using extends inheritance
class Square extends Rectangle {

  //By default, the nonparametric construction of the parent class will be accessed. If the parent class does not have a parameterless construct, you need to explicitly specify which construct to call
  Square(double width):super(width, width);

  //Methods that override the parent class
  @override
  double getArea() {
    //Using super to access the member variables of the parent class
    Print ('override parent method: ${super_ width}');
    //Using super to access member methods of a parent class
    return super.getArea();
  }
}

void main() {
//   Square.getName (); error, static member cannot be inherited
//   Square.name ; error, static member cannot be inherited
  Square square = Square(10);
  print(square.getArea());
  print(square._width);
}

abstract class

main points:

  • Add abstract keyword before class to define abstract class
  • Abstract classes cannot be instantiated, they can only be inherited (I will talk about later, they can also be implemented as interfaces)
  • Abstract classes can have abstract methods (methods without method body), ordinary methods and member variables
  • This class is either abstracted, or all classes are abstractednoSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);method
//Define an abstract class
abstract class Shape {
  //Abstract method, no method body
  double getArea();

  double getPerimeter();
}

class Rectangle extends Shape {
  double _height;
  double _width;

  Rectangle(double width, double height) {
    this._width = width;
    this._height = height;
  }

  Rectangle.fromMap(Map<String, double> map) {
    this._width = map['width'];
    this._height = map['height'];
  }

  //The abstract method of an abstract class must be overridden, otherwise it needs to be declared as an abstract class
  @override
  double getArea() {
    return _height * _width;
  }

  //Abstract methods of abstract classes must be overridden
  @override
  double getPerimeter() {
    return _height + _width;
  }
}

void main() {
//Shape shape = shape(); error, abstract class cannot be instantiated

  Shape shape = rectangle (10, 2); // this is OK
  print(shape.getArea());
  print(shape.getPerimeter());
}

Interface

As for the interface, dart has a strange design.

The official document describes the interface

Each class explicitly declares an interface that contains its member variables, member methods and the interfaces it implements. If you want to create a class that supports class B API, implement class B.

In other words, defining a class is equivalent to defining an interface. You can directly implement it or implement multiple interfaces. Extensions can only inherit one class, and implements can implement multiple classes (sorry to say that one class is implemented, here is the interface).

In the previous example, it’s OK to write it directly below

class Rectangle implements Shape

generic paradigm

Dart provides support for generics, which can increase the generality of programs, and provide some static checks, which reduces the work of cast.

//Defining a generic class
class Cache<T> {
  Map<String, T> _cache = {};

  T getByKey(String key) {
    return _cache[key];
  }

  //Generic methods
  void setByKey(String key, T value) {
    _cache[key] = value;
  }
}

//For type constraint, it must be a subclass of num
class NumCache<T extends num> {
  Map<String, T> _cache = {};

  T getByKey(String key) {
    return _cache[key];
  }

  void setByKey(String key, T value) {
    _cache[key] = value;
  }
}

void main() {
  Cache<String> cache = Cache();
  cache.setByKey("a", "1");
//   cache.setByKey ("B", 2); error, type mismatch
  print( cache.getByKey ("a") is string); // the type is kept and the output is true

//Numcache < string > numcache = numcache(); error string is not a subclass of num
  NumCache<int> numCache = NumCache();
  numCache.setByKey('a', 1);
}

abnormal

main points:

  • There is no need to explicitly specify which exceptions to throw, unlike Java, which uses the throws exception class
  • It is not necessary to handle exceptions. Java must catch throws if it has throws
  • There are error, exception and their subclasses as exception classes, which can also be customized
  • When you throw an exception, you can throw an exception class or any object that is not null
  • You can use try catch to handle the exception, or you can throw it up again
//Throw an exception instance
void testThrow() {
  Throw exception;
}

//You can throw an arbitrary object
void testThrow2() {
  Throw "throw string is OK";
}

void testThrow3() {
  try {
    testThrow();
  } catch(e) {
    //If an exception is caught, it will not be handled and thrown up again
    rethrow;
  }
}

void main() {
  try {
    testThrow();
  }Catch (E, s) {// where e is the exception class thrown and S is the stack information
    print(e is Exception); // true
    print(s);
  }

  try {
    testThrow2();
  } catch(e) {
    print(e is Exception); // false
    Print (E); // you can also throw a string
  }
  
  Testthrow3(); // if there is an exception thrown here, it can pass the static check if it is not caught
  //The following statement cannot be executed
  Print ("can I execute without catching the exception?";
}

Asynchronous programming

Dart provides asynchronous support. The core classes, including future and stream, are located in thedart:asyncPackage, here is a very common future

Future is used to represent a class whose value or error will be known in the future, similar to promise in JS.

  1. The creation of future

You can create a future using the construction method of future

  • Future (futureor < T > calculation()) can execute the calculation function asynchronously, and the result is the result of future
  • Future Future.delayed (duration, [futureor < T > calculation()]) is delayed to execute the function inside
  • Future Future.error (object error, [stacktrace stacktrace]) throws an error late
  • Future.sync (futureor < T > calculation())
  • Future Future.microtask (futureor < T > calculation()) is executed as a micro task
  • Future Future.value The parameter ([futureor < T > value]) is a future, and the return value of the parameter is taken as the return value of the future

These construction methods are relatively simple to use. The following is a simple example

//Use unnamed constructs
Future<String> getFuture() {
  return Future<String>(() {
    return "hello";
  });
}

// Future.delayed
Future<String> getFuture2() {
  return Future.delayed(Duration(seconds: 2), () {
    return "Future.delayed";
  });
}

// Future.error
Future<String> getFuture3() {
  return  Future.error ("error object");
}

// Future.microtask
Future<String> getFuture4() {
  return Future.microtask(() {
    return "Future.microtask";
  });
}

// Future.sync
Future<String> getFuture5() {
  return Future.sync(() {
    return "Future.sync";
  });
}

Future.value(getFuture4());

For the comparison of delayed, microtask and sync, please refer to the following article

  1. Obtaining future results
  • If a function returns future, you can use async wait to get its result and try catch to catch the exception
  • You can use. Then to get the normal result and. Catcherror to get the thrown exception
import 'dart:async';

//Use unnamed constructs
Future<String> getFuture() {
  return Future<String>(() {
    return "hello";
  });
}

void method1() {
  getFuture().then((res) {
    print(res);
  }).catchError((e) {
    print(e);
  });
  Print ("the next one is executed first");
}

void method2() async {
  String str = await getFuture();
  print(str);
  Print ('execute in order ');
}

void main(){
  method1();
  method2();
  //Output
  //The last one is executed first
  // hello
  // hello
  //Execute in order
}
  1. Future execution order comparison

It is concluded that the test has passed the test

  • Microtask and async are written first
  • Using the constructor directly is executed last
  • Delayed is executed after microtask and async

The students who are interested in the comparison can study it by themselves.

Network request

There are two common methods to send network requests

  • One is to use dart:io Httpclient under
  • The second is to use package:http/http.dart

HttpClient

Use steps:

  • Create httpclient
  • [optional] configure httpclient, such as setting timeout, proxy, etc
  • Get httpclientrequest
  • [optional] set httpclientrequest, such as header
  • Get httpclientresponse
  • Processing response results
  • Close connection
import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:flutter/cupertino.dart';

//This encapsulates a method to send a get request to deserialize the returned JSON string
Future<Map<String, dynamic>> httpGet(
    {@required String url,
    Map<String, dynamic> headers = const {},
    Map<String, dynamic> params = const {},
    int timeout = 10}) async {
  //Create httpclient instance
  HttpClient client = HttpClient();
  //I start a proxy service locally to facilitate packet capture. No proxy service can be removed
  client.findProxy = (uri) {
    //If you need to filter the URI, you can judge it manually
    return "PROXY 127.0.0.1:8888";
  };
  //Timeout setting
  client.connectionTimeout = Duration(seconds: timeout);
  //The URI object is created through the URL (including the protocol host path) to obtain each part of the URL
  Uri uri = Uri.parse(url);
  //Creating an httpclientrequest object using geturl
  HttpClientRequest httpClientRequest = await client.getUrl(Uri(
      scheme: uri.scheme,
      host: uri.host,
      path: uri.path,
      queryParameters: params));
  //Add custom header
  headers.forEach((key, value) {
    httpClientRequest.headers.add(key, value);
  });

  //Call the close of httpclientrequest to get the httpclientresponse
  HttpClientResponse httpClientResponse = await httpClientRequest.close();
  //Decode using a specific character set
  var str = await httpClientResponse.transform(utf8.decoder).join();
  //Serialize the string to map, which will be explained later
  Map<String, dynamic> map = jsonDecode(str);
  //Close connection
  client.close(force: false);
  return map;
}

void main() async {
  Map<String, dynamic> map = await httpGet(
      url: 'http://t.weather.sojson.com/api/weather/city/101030100',
      headers: <String, dynamic>{
        'custom_header': 'customheader',
      },
      params: <String, dynamic>{
        "version": 'v1',
        'cityid': '101120201',
        'city': 'Qingdao'
      });

  print(map);
}

The above code simply encapsulates a method to send a get request. The parameters of get request are carried on the URL, but post is different. The parameters of post are usually in the body. The following shows how to send a post request. The data format is JSON, and the form format is similar. Just modify the application.

void main() async {
  HttpClient client = HttpClient();
  //Set up a service locally for testing
  HttpClientRequest httpClientRequest = await client.postUrl(Uri.parse('http://127.0.0.1:3000/users/save'));

  //The key step is to tell the server the format of the request parameters
  httpClientRequest.headers.contentType
  = new ContentType("application", "json", charset: "utf-8");
  //Key step, write data to body
  httpClientRequest.write(jsonEncode({"name":'lily', 'age': 20}));
  HttpClientResponse httpClientResponse = await httpClientRequest.close();
  var str = await httpClientResponse.transform(utf8.decoder).join();
  Map<String, dynamic> map = jsonDecode(str);
  print(map);
}

There are also about the content of the upload file, this article is too long, write a later.

http

We found that it is troublesome to use native httpclient to send requests. We can use package:http/http.dart This package can greatly simplify development. Please refer to the above for package installationmodularizationpart

import 'package:http/http.dart' as http;

void main() async {
  //Demo post request
  var url = 'http://127.0.0.1:3000/users/save';
  var response = await http.post(url, body: {'name': 'lily', 'age': '20'});
  print('Response status: ${response.statusCode}');
  print('Response body: ${response.body}');

  //Demo get request
  var response2 = await http.get('http://127.0.0.1:3000?a=1',);
  print(response2.body);

}

Can be found and usedpackage:http/http.dartExtremely convenient.

JSON serialization and deserialization

JSON is a very flexible data exchange format.

Generally speaking, JSON serialization and deserialization are to convert language defined non string types (such as entity classes in Java and map in DART) into JSON strings for easy transmission and storage. This is serialization; deserialization is the inverse process, which is convenient for data operation.

In Java, Alibaba’s fastjson is generally used to serialize and deserialize JSON;

Using in JS JSON.stringify ()、 JSON.parse () for serialization and deserialization.

There are two ways to serialize and deserialize JSON in dart

  • One is to use the built-in library dart:convert Jsondecode and jsonencode of
  • The second is to use package:json_ Serializable, this library is similar to the second method mentioned in the next question, except that it will automatically generate the template code mentioned below for you, which will not be described in detail here.

use dart:convert

  1. Do not pay attention to types, and use dynamic types directly. This way will lead to type checking that can’t be wrong. It may be unsafe. The advantage is that it is simple and does not need to write entity classes
import 'dart:convert';

void main() async {
  String jsonString = '[{"name":"name1","age":1},{"name":"name2","age":2}]';
  List list = jsonDecode(jsonString);

  list.forEach((item) {
    print(item['name']);
  });
  String jsonString2 = jsonEncode(list);
  print(jsonString2);
}
  1. Using type conversion and defining some conversion rules in entity class has the advantage of static type checking, but it is troublesome
import 'dart:convert';

class User {
  String name;
  int age;

  User(this.name, this.age);

  //Convert map to user
  User.fromJson(Map<String, dynamic> json) {
    name = json['name'];
    age = json['age'];
  }

  //Convert user to map
  Map<String, dynamic> toJson() =>
      {
        'name': name,
        'age': age,
      };
}

void main() async {

  List<User> list = List();

  list.add(User('name1', 1));
  list.add(User('name2', 2));

  //Tojson is called automatically here
  String str = jsonEncode(list);
  print(str.runtimeType); // String
  print(str); // [{"name":"name1","age":1},{"name":"name2","age":2}]

  //Here you want to deserialize to list < user > but no method has been found,
  //Online documents are basically translated into official documents, and no solution has been found on the official website
  List userList = jsonDecode(str);

  userList.forEach((item) {
    //It has to be forced manually
    User u = User.fromJson(item);
    print(u.name);
  });

  // name1
  // name2
}

Because of the reason for writing JS before, we prefer to use the first method, because we don’t need to write entity classes. Moreover, even if the second scheme is converted to a specific type, it has no great significance except that you can use. To directly access properties. JS doesn’t have this habit of defining entity classes and plays as usual.

Last words

I thought I could finish dart in a few words, but I found that I wrote more than 1300 lines and omitted some trivial things (such as dart’s collection framework).

I wish you all a happy flight! ~

Finally, I present the small welfare mentioned at the beginning of the article. The picture is small and inconvenient to viewDownload source fileFor the download address of the mind map source file, please refer toMind mapIf you can, help to point a star A kind of

Getting started with dart

reference

Recommended Today

Summary of recent use of gin

Recently, a new project is developed by using gin. Some problems are encountered in the process. To sum up, as a note, I hope it can help you. Cross domain problems Middleware: func Cors() gin.HandlerFunc { return func(c *gin.Context) { //Here you can use * or the domain name you specify c.Header(“Access-Control-Allow-Origin”, “*”) //Allow header […]