Flutter入门学习(三)— Dart语言详解

本文的所有内容均是官方文档的简单翻译和理解。
主要介绍Dart语言[变量、内置类型、函数、类、泛型、异常、库、生成器、元数据(注解)]
本人以实际代码案例为主,可以直接复制Android studio运行学习。

变量

变量的声明

  • var
  • dynamic
  • Object

变量的默认值

  • 没有初始化的变量自动获取一个默认值为null
  • 一切皆对象,对象的默认值为null

final和const

  • 共同点:
    • 1.声明的类型可省略
    • 2.初始化后不能再赋值
    • 3.不能和var同时使用
  • 不同点(需要注意的地方)
    • 1.类级别常量,使用static const
    • 2.const可使用其他const 常量的值来初始化其值
    • 3.使用const赋值声明,const可省略
    • 4.可以更改非final、非const变量的值,即使曾经具有const值
    • 5.const导致的不可变性是可传递的
    • 6.相同的const常量不会在内存中重复创建
    • 7.const需要是编译时常量

内置类型

num, int, double

  • int : 整数值
  • double : 64-bit双精度浮点数
  • int和double是num的子类

String

  • Dart 字符串是 UTF-16 编码的字符序列,可以使用单引号或者双引号来创建字符串
  • 可以使用三个单引号或者双引号创建多行字符串对象
  • 可以使用 r 前缀创建”原始raw”字符串
  • 可以在字符串中使用表达式: ${expression},如果表达式是一个标识符,可以省略 {},如果表达式的结果为一个对象,则 Dart 会调用对象的 toString() 函数来获取一个字符串

bool

  • bool对象未初始化的默认值是null

List

  • Dart中可以直接打印list包括list的元素,List也是对象。java中直接打印list结果是地址值
  • Dart中List的下标索引和java一样从0开始
  • 和java一样支持泛型
  • 有增删改查,支持倒序,自带排序、洗牌,可使用+将两个List合并

Map

  • 跟java类似,不做详解

Set

  • set1.difference(set2):返回set1集合里有但set2里没有的元素集合
  • set1.intersection(set2):返回set1和set2的交集
  • set1.union(set2):返回set1和set2的并集
  • set1.retainAll():set1只保留某些元素(要保留的元素要在原set中存在)

Runes路由

Main(){
  Runes runes = new Runes('\u{1f605} \u6211‘);
  var str1 = String.fromCharCodes(runes);  
  print(str1);
}

Symbol

  • Symbol标识符,主要是反射用,现在mirrors模块已经被移除

函数

  • 可在函数内定义
  • 定义函数时可省略类型
  • 定义函数时可省略类型

可选参数

  • 可选命名参数
  • 可选位置参数
  • 默认参数值

匿名函数

  • 可赋值给变量,通过变量调用
  • 可在其他函数中直接调用或传递给其他函数

闭包

Function makeAddFunc(int x) {
  x++;
  return (int y) => x + y;
}

main() {
  var addFunc2 = makeAddFunc(2);
  var addFunc4 = makeAddFunc(4);
  print(addFunc2(3));
  print(addFunc4(3));
}

函数别名

typedef Fun1(int a, int b);
typedef Fun2<T, K>(T a, K b);
int add(int a, int b) {
  print('a + b');
  return a + b;
}
class Demo1 {
  Demo1(int f(int a, int b), int x, int y) {
    var sum = f(x, y);
    print("sum1 = $sum");
  }
}
class Demo2 {
  Demo2(Fun1 f, int x, int y) {
    var sum = f(x, y);
    print("sum2 = $sum");
  }
}
class Demo3 {
  Demo3(Fun2<int, int> f, int x, int y) {
    var sum = f(x, y);
    print("sum3 = $sum");
  }
}

操作符
在这里插入图片描述

流程控制语句

  • if else
  • for, forEach, for-in
  • while , do-while
  • break ,continue
  • switch case

异常

Exception类型
在这里插入图片描述

Error类型
在这里插入图片描述

异常抛出

// 抛出Exception 对象
 throw new FormatException(‘格式异常');

// 抛出Error 对象
 throw new OutOfMemoryError();

// 抛出任意非null对象
 throw '这是一个异常';

异常捕获

try {
  throw new OutOfMemoryError();
} on OutOfMemoryError {
  print('没有内存了');
} on Error catch(e) {
  print('Unknown error: $e');
} catch (e, s) {
  print('Exception details: $e');
  print('Stack Trace: $s');
} finally {
  print('end');
} 

构造函数

  • Java中写法
class Point {
  double x;
  double y;

  Point(int x, int y) {
    this.x = x;
    this.y = y;
  }
}
  • Dart建议写法
class Point {
  num x;
  num y;
  Point(this.x, this.y);
}

命名构造函数

class Point { 
  num x; 
  num y; 

  Point(this.x, this.y); 

  //命名构造函数
  Point.fromJson(Map json) { 
    x = json['x']; 
    y = json['y']; 
  } 
}

重定向构造函数

class Point { 
  num x; 
  num y; 

  Point(this.x, this.y); 

  //重定向构造函数,使用冒号调用其他构造函数
  Point.alongXAxis(num x) : this(x, 0);
}

初始化列表

import 'dart:math';

class Point {
  //final变量不能被修改,必须被构造函数初始化
  final num x;
  final num y;
  final num distanceFromOrigin;

  //初始化列表
  Point(x, y)
      : x = x,
        y = y,
        distanceFromOrigin = sqrt(x * x + y * y);
}

调用超类构造函数

class Parent {
  int x;
  int y;

  //父类命名构造函数不会传递  
  Parent.fromJson(x, y)
      : x = x,
        y = y {
    print('父类命名构造函数');
  }
}
class Child extends Parent {
  int x;
  int y;
  //若超类没有默认构造函数, 需要手动调用超类其他构造函数
  Child(x, y) : super.fromJson(x, y) {
    //调用父类构造函数的参数无法访问 this
    print('子类构造函数');
  }

  //在构造函数的初始化列表中使用super(),需要把它放到最后
  Child.fromJson(x, y) 
	 : x = x,
	   y = y,
	   super.fromJson(x, y) {
    print('子类命名构造函数');
  }
}

常量构造函数

class Point2 {
  //定义const构造函数要确保所有实例变量都是final
  final num x;
  final num y;
  static final Point2 origin = const Point2(0, 0);

  //const关键字放在构造函数名称之前,且不能有函数体
  const Point2(this.x, this.y);
}

工厂构造函数

class Singleton {
  String name;
  //工厂构造函数无法访问this,所以这里要用static
  static Singleton _cache; 

  //工厂方法构造函数,关键字factory
  factory Singleton([String name = 'singleton']) =>
      Singleton._cache ??= Singleton._newObject(name);

  //定义一个命名构造函数用来生产实例
  Singleton._newObject(this.name);
}

Setter和Getter

class Rectangle {
  num left;
  num top;
  num width;
  num height;

  Rectangle(this.left, this.top, this.width, this.height);

  num get right => left + width;
  set right(num value) => left = value - width;
  num get bottom => top + height;
  set bottom(num value) => top = value - height;
}

抽象类

  • abstract关键字修饰class
  • 继承的方式使用
  • 接口的方式使用

可调用类

class ClassFunction {
  call(String a, String b, String c) => '$a $b $c!';
}

main() {
  var cf = new ClassFunction();
  var out = cf("dongnao","flutter","damon");
  print('$out');
  print(cf.runtimeType);
  print(out.runtimeType);
  print(cf is Function);
}

泛型

泛型函数

main() {
  K addCache<K, V>(K key, V value) {
    K temp = key;
    print('${key}: ${value}');
    return temp;
  }
  var key = addCache('dongnao', 'damon');
  print(key);
}

构造函数泛型

main() {
  var p = Phone<String>('123456');
  print(p.mobileNumber);
}

class Phone<T> {
  final T mobileNumber;
  Phone(this.mobileNumber);
}

泛型限制

main() {
  var footMassage = FootMassage();
  var m = Massage<FootMassage>(footMassage);
  m.massage.doMassage();
}

class Massage<T extends FootMassage > {
  final T massage;
  Massage(this.massage);
}

class FootMassage {
  void doMassage() {
    print('脚底按摩');
  }
}

Dart泛型与Java泛型区别

  • Java中的泛型信息是编译时的,泛型信息在运行时是不存在的
  • Dart的泛型类型是固化的,在运行时也有可以判断的具体类型
var names = List<String>();
print(names is List<String>);//true
print(names.runtimeType); // List<String> 

载入第三方库

  1. 编写pubspec.yaml:
dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^0.1.0
  dio: ^2.1.0
  1. 调用
import "package:dio/dio.dart";

void main() {
  getHttp();
}

void getHttp() async {
  try {
    Response response = await Dio().get("https://www.baidu.com");
    print(response);
  } catch (e) {
    print(e);
  }
}

载入文件

//Mylib1.dart
class MyLib {
  String name;
  static MyLib _cache; 
  factory MyLib([String name = 'singleton']) =>
      MyLib._cache ??= MyLib._newObject(name);

  MyLib._newObject(this.name);
}
import “mylib1.dart";

void main() {
  var myLib1 = MyLib();
}

指定库前缀

如果两个库有冲突的标识符,可以为其中一个或两个库都指定前缀:

import 'MyLib1.dart' as lib1; 
import 'MyLib2.dart' as lib2; 

void main() {
  var myLib = lib1.MyLib();
  var myLib2 = lib2.MyLib();
}

选择性载入

  • show-只载入库的某些部分
  • hide-筛选掉库的某些部分
import 'Mylib1.dart' as lib1 show Test;
import 'Mylib2.dart' as lib2 hide Test;

var test = lib1.Test();
var lib = lib2.MyLib();

延迟载入

  • 使用deferred as导入
  • 使用标识符调用loadLibrary()加载库
import 'MyLib1.dart' deferred as lazyLib;

void main() {
  lazyLoad();
}
lazyLoad() async {
  await lazyLib.loadLibrary();
  var t = lazyLib.Test();
  t.test();
}

异步

异步-async和await

void main(){
  getName1();
  getName2();
  getName3();
}

Future getName1() async {
  await getStr1();
  await getStr2();
  print('getName1’);
}
getStr1() {
  print('getStr1’);
}
getStr2() {
  print('getStr2’);
}
getName2() {
  print('getName2’);
}
getName3() {
  print('getName3’);
}

异步-then,catchError,whenComplete

void main() {
  new Future(() => futureTask())//异步任务的函数
      .then((m) => "result:$m")//任务执行完后的子任务
      .then((m) => m.length) //其中m为上个任务执行完后的返回的结果
      .then((m) => printLength(m))
	  .catchError(print)
      .whenComplete(() => whenTaskCompelete());//所有任务完成后的回调函数
}

Event-Looper
在这里插入图片描述

异步-Event Queue和Microtask Queue
在这里插入图片描述

异步-任务调度

  • 使用Future类,可以将任务加入到Event Queue的队尾
  • 使用scheduleMicrotask函数,将任务加入到Microtask Queue队尾
    在这里插入图片描述

异步-new Future()

void main(){
  testFuture();
}
void testFuture() {
  Future f = new Future(() => print('f1'));
  Future f1 = new Future(() => null);
  //Future f1 = new Future.delayed(Duration(seconds: 1) ,() => null);
  Future f2 = new Future(() => null);
  Future f3 = new Future(() => null);
  f3.then((_) => print('f2'));
  f2.then((_) {
    print('f3');
    new Future(() => print('f4'));
    f1.then((_) {
      print('f5');
    });
  });
  f1.then((m) {
    print('f6');
  });
  print('f7');
}

异步-scheduleMicrotask()

import 'dart:async';
void main(){
  testFuture();
}
void testScheduleMicrotask(){
  scheduleMicrotask(() => print('s1'));

  new Future.delayed(new Duration(seconds: 1), () => print('s2'));

  new Future(() => print('s3')).then((_) {
    print('s4');
    scheduleMicrotask(() => print('s5'));
  }).then((_) => print('s6'));

  new Future(() => print('s7'));

  scheduleMicrotask(() => print('s8'));

  print('s9');
}

生成器

生成器-同步生成器

Main(){
  var it = getSyncGenerator(5).iterator;
  while (it.moveNext()) {
    print(it.current);
  }
}

Iterable<int> getSyncGenerator(int n) sync* {
  print('start');
  int k = 0;
  while (k < n) {
    yield k++;
  }
  print('end');
}

生成器-异步生成器

Main(){
//getAsyncGenerator(5).listen((value) => print(value));
  StreamSubscription subscription = getAsyncNumIterator(5).listen(null);
  subscription.onData((value) {
    print(value);
    if(value>=2){
      subscription.pause();
    }
  });
}

Stream<int> getAsyncGenerator(int n) async* {
  print('start');
  int k = 0;
  while (k < n) {
	yield k++;
  }
  print('end');
}

生成器-递归生成器

Main(){
  var it = getSyncRecursiveGenerator(5).iterator;
  while (it.moveNext()) {
    print(it.current);
  }
}

Iterable<int> getSyncRecursiveGenerator(int n) sync* {
  if (n > 0) {
    yield n;
    yield* getSyncNumDownFrom(n - 1);
  }
}

元数据

(注解)-@deprecated

main() {
  dynamic tv = new Television();
  tv.activate();
  tv.turnOn();
}

class Television {
  @deprecated
  void activate() {
    turnOn();
  }

  void turnOn() {
    print('Television turn on!');
  }
}

(注解)-@override

main() {
  dynamic tv = new Television();
  tv.activate();
  tv.turnOn();
  tv.turnOff();
}

class Television {
  @deprecated
  void activate() {
    turnOn();
  }
  
  void turnOn() {
    print('Television turn on!');
  }
  @override
  noSuchMethod(Invocation mirror) {
    print('没有找到方法');
  }
}

(注解)-自定义

//todo.dart

class Todo {
  final String who;
  final String what;

  const Todo({this.who, this.what});
}
import 'todo.dart’;

main() {
  dynamic tv = new Television();
  tv.doSomething();
}

class Television {
  @Todo(who: 'damon', what: 'create a new method')
  void doSomething() {
    print('doSomething');
  }
}
发布了37 篇原创文章 · 获赞 35 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/jaynm/article/details/105251710