Flutter 学习7:Dart语言基础

Categories: flutter
  1. Flutter 学习1:开发环境、开发工具、初始化一个项目
  2. Flutter 学习2:从main.dart文件说起
  3. Flutter 学习3:转场、导航
  4. Flutter 学习4:集成到原有的项目中
  5. Flutter 学习5:开发Dart包和插件包
  6. Flutter 学习6:绘制动画
  7. Flutter 学习7:Dart语言基础
  8. Flutter 学习8:BottomSheet
  9. Flutter 学习9:Positioned、Transform等控件使用以及手势控制
  10. Flutter 学习10:NestedScrollView、SliverAppBar、TabBar

这些概念其实一开始就应该去弄明白的,当时接触Flutter的时候发现跟Java很类似,也就没有花时间去看看文档,后来在用的过程中发现还是有必要看看文档的,不然在开发中经常会遇到很多语法上面的疑惑再去查文档,蛮浪费时间的。

关键概念

 Object s = 'this is string';
  s = 8;
  print(s.toString()); // 这里s是Object对象,只能执行Object的函数
  dynamic s = 'this is string';
  if (s is String) {
    print(s); // 打印this is string
  }
  s = 8;
  if (s is int) {
    s++; // 自动推断是int类型
    print(s.toString()); // 打印9
  }

这里的is关键字就是判断变量类型的,并且还有智能推断作用,只要通过了判断,if内部的语句中这个变量类型就是对应的判断成功的类型。

变量

和其他语言一样Dart定义了很多常见的基本变量类型,int、double、String、bool等,其中int、double都是64位的。但前面说了Dart是有类型推断的,所以一般变量可以用var关键字表示。还有常量可以用finalconst表示,他们两区别是final是运行时常量,const是编译时常量。

基本类型

  String s = 'this is string';
  int n = 1;
  double d = 1.0;
  bool b = true;
  
  final String s = 'this is string';
  final int n = 1;
  final double d = 1.0;
  final bool b = true;
  
  const String s = 'this is string';
  const int n = 1;
  const double d = 1.0;
  const bool b = true; 

也可以这样写:

  var s = 'this is string';
  var n = 1;
  var d = 1.0;
  var b = true;
  
  final s = 'this is string';
  final n = 1;
  final d = 1.0;
  final b = true;
  
  const s = 'this is string';
  const n = 1;
  const d = 1.0;
  const b = true; 

String

字符串可以用 + 连接,字符串内部还可以用$表示变量。

  var s1 = 'this is string';
  var s2 = 's1:$s1';
  var s3 = 's1:'+ s1;
  if (s2 == s3) {
    print('true');
  }

Lists、Maps、Sets

Lists

List 就跟js里的数组差不多,它可以直接用字面量新建:

var list = [1, 2, 3];
//指定泛型
vat list1 = <int>[];

也可以用List的构造器新建:

var list = List<int>();

定义不可变数组:

var list2 = const [1, 2]; //数组前加了const就不能改变这个数组了
list2.add(3);// 错误
list2 = [2, 3]; // list2本身是变量 所以这样是可以的

可以通过下标修改值:

var list = [1, 2, 3];
list[1] = 1;
assert(list[1] == 1);

Maps

Map和List一样可以通过字面量和构造器定义:

  var map = const{
    'key1': 'value1',
    'key2': 'value2'
  };
  var map1 = Map();
  map1['key1'] = 'value1';
  map1['key2'] = 'value2';
  // 指定泛型
  var map2 = Map<String, String>();

如果没有对应的key找出来的值就是null:

assert(map['key'] == null);

Sets

Set只能通过构造器定义:

  var set = Set<String>();
  set.add('123');
  if(set.contains('123')){
    print('true');
  }

函数

Dart中的函数和Java有点类似。

void abc() {
}

支持可选参数:

void abc(int i,[int l]){
}
// 也支持默认值
void fo(int i, [int l = 9]) {
}
void main() {
abc(1);
abc(1, 2);
}

还支持具名参数,具名参数也可以有默认值:

void abc({int x, int y = 0}){
}
void main() {
abc(x: 1);
abc(x: 1, y:2);
}

函数还可以定义为变量,可以用别名表示:

typedef abc = int Function(int, int);
void main() {
  abc a = (int i, int j) {
    return i+j;
  } ;
  var r = a(1, 2);
  print(r);
}

甚至还能在函数内部定义函数:

typedef abc = int Function(int, int);

abc generateAbc(int z) {
  int xyz(int x, int y) {
    return x + y + z;
  }
  return xyz;
}

void main() {
  var r = generateAbc(1);
  print(r(2, 3));
}

如果函数内部只有一句语句还可以用 => 符号简化:

  int xyz(int x, int y) {
    return x + y ;
  }
  //跟上面等价
  int xyz(int x, int y)  => x+y;

操作控制语句

// 瀑布流写法 这个比较有意思
querySelector('#confirm') // Get an object.
  ..text = 'Confirm' // Use its members.
  ..classes.add('important')
  ..onClick.listen((e) => window.alert('Confirmed!'));

上面这种中间两个点连接的写法是啥意思呢,跟下面的写法是等价的:

var button = querySelector('#confirm');
button.text = 'Confirm';
button.classes.add('important');
button.onClick.listen((e) => window.alert('Confirmed!'));

控制语句

//if
if (isRaining()) {
  you.bringRainCoat();
} else if (isSnowing()) {
  you.wearJacket();
} else {
  car.putTopDown();
}
//for
for (var i = 0; i < 5; i++) {
  print('i:$i');
}
//for in
for (var x in collection) {
  print(x); 
}
//while
while (!isDone()) {
  doSomething();
}
//do while
do {
  printLine();
} while (!atEndOfPage());
//switch
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();
}

异常

抛出异常:

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

它还可以抛出普通类型的对象:

throw 1001;

捕获异常:

try {
  breedMoreLlamas();
} on OutOfLlamasException {
  // A specific exception
} on Exception catch (e) {
  // Anything else that is an exception
} catch (e) {
  // No specified type, handles all
}

类定义跟Java差不多,参数传入构造函数:

class P {
  var x;
  var y;
  P(int x, int y) {
    this.x = x;
    this.y = y;
  }
}

但是Dart可以简化:

class P {
  var x;
  var y;
  P(this.x, this.y) ;
}

当然跟函数一样也可以定义具名参数:

class P {
  var x;
  var y;
  P({this.x, this.y}) ;
}

void main() {
  P(x: 1, y: 2);
}

Dart类还有一个Initializer lists的概念,初始化类内部参数用的:

class P {
  var x;
  var y;
  P(int x, int y): x = x, y = y ;
}

这里冒号后面的语句就是Initializer lists,它会在构造函数执行前执行,它会识别等号前面那个x是类内部的x变量。 类继承很简单使用extends关键字,super是跟在 Initializer lists 后面:

class P {
  var x;
  var y;
  P(int x, int y): x = x, y = y ;
}

class Q extends P {
  int z;
  Q(int x, int y, int z): z = z, super(x, y) ;
}

访问控制

Dart没有public、private这样的访问权限关键字,它都是用package分割的。默认如果不想让外部访问命名的时候可以用下划线开头:

class _Abc {
}
class Abc {
    int _i;
}

访问外部包需要引入:

import 'dart:html';

也可以只引入某一个需要的文件:

import 'package:test/test.dart';

防止冲突还可以使用别名:

import 'package:lib2/lib2.dart' as abc;
//使用的时候
abc.Element element2 = abc.Element();

控制某些单独的对象引入:

// 这里只引入了foo对象
import 'package:lib1/lib1.dart' show foo;
// 这里是除了foo对象
import 'package:lib2/lib2.dart' hide foo;

甚至极端一点还可以运行时加载外部包,这样可以更快速的启动应用,或者有些业务场景下异步加载模块的时候可以用:

import 'package:greetings/hello.dart' deferred as hello;

使用的时候需要异步加载外部包:

Future greet() async {
  await hello.loadLibrary();
  hello.printGreeting();
}