flutter-dart菜鸟入门
本人是一名Android开发,这是个人在学习flutter的过程中对dart的一些学习总结和自己的理解,如果发现什么写的不对的地方,请勿喷
本文只是简单介绍开发flutter的dart的常用用法,强烈建议阅读官方文档dart中文网地址
1. 为什么要介绍dart?
因为 Flutter 需要使用Dart语言开发;
2. 基本数据类型
- num 数字, 包括整数和浮点数
- int 整数
- double 浮点数
- String 字符串
- bool 布尔值
3. 重要的概念
- dart所有对象类都继承 Object
- dart所有变量都是对象,包括数字、null等都是对象
- dart所有类型变量的默认值全是null(包括数字类型和布尔类型)
- dart跟Java不同,没有 public、 protected、 和 private 修饰符;私有变量以 (_) 开头,否则是就是公有的
- 当dart 需要一个布尔值的时候,只有 true 对象才被认为是 true,其他任何情况都是false,这点和 JavaScript 不一样
- dart支持高阶函数、顶级函数、顶级变量、静态函数、静态变量等
4. 定义变量
用var定义一个可变类型的变量
var name = 'Bob';
name = 1;
name = false;
定义具体类型的变量
String name = 'Bob'; // 定义一个字符串变量
bool flag = false; // 定义一个布尔类型变量
int age = 10; // 定义一个整数变量
建议:成员变量使用具体的类型,var只在局部变量中使用。代码风格
5. 定义常量
支持使用final和const定义常量
- final 变量只能赋值一次
- const 变量是编译时常量(Const 变量同时也是 final 变量)
final name = 'Bob';
const bar = 1000000;
const atm = 1.01325 * bar;
6. const 其他用法
创建不变的值
var foo = const []; // 定义一个不可变的集合
boo.add(1); // error
定义常量构造函数
class A {
const A();
}
A a1 = const A();
A a2 = const A();
print(a1 == a2); // true
7. 字符串
- 可以使用单引号或者双引号来创建字符串
- 在字符串中可以使用${expression}表达式
- 可以使用三个单引号或者双引号创建多行字符串
var s1 = 'Single quotes work well for string literals.';
var s2 = "Double quotes work just as well.";
var s3 = "expression $s2";
var s4 = "expression ${s2.toUpperCase()}";
var s5 = '''
You can create
multi-line strings like this one.
''';
var s6 = """This is also a
multi-line string.""";
8. 定义class
- 所有的类都继承于 Object
- 不支持多继承,但支持基于 mixin 的继承机制,意味着每个类(Object 除外) 都只有一个超类
- 无法像java一样直接定义interface,但支持隐式接口,每个类都隐式的定义了一个包含所有实例成员的接口, 并且这个类实现了这个接口
- 使用abstract 修饰符定义一个抽象类,抽象类通常用来定义接口, 以及部分实现
// 定义class Person
class Person {
// In the interface, but visible only in this library.
final _name;
// Not in the interface, since this is a constructor.
Person(this._name);
// In the interface.
String greet(who) => 'Hello, $who. I am $_name.';
}
// 定义Imposter 实现Person隐式的interface
class Imposter implements Person {
// 需要实现interface _name属性
final _name = "";
// 需要实现interface greet方法
String greet(who) => 'Hi $who. Do you know who I am?';
}
// 定义Imposter1 继承Person类
class Imposter1 extends Person {
Imposter1(name) : super(name);
}
定义抽象类
abstract class AbstractContainer {
// 抽象方法不需要用abstract修饰符
void updateChildren();
}
// 继承抽象类
class SpecializedContainer extends AbstractContainer {
// 实现抽象方法
void updateChildren() {
// ...Implement updateChildren()...
}
}
// 实现抽象类AbstractContainer 隐式的interface
class SpecializedContainer1 implements AbstractContainer {
// 实现interface的方法
void updateChildren() {
// ...Implement updateChildren()...
}
}
9. mixin 继承机制(为类添加新的功能)
- 定义mixin 跟定义class一样,但是不能有构造函数,连无参的构造函数都不行;因为每个Mixin都有一个自定义的构造函数被单独调用,父类也是如此,因此Mixin的构造函数不能够被声明,调用函数可以省略
- 使用 with 关键字 使用mixin
- 使用mixin定义的class,是所有mixin类的子类
class A {
void printA() {
print("A");
}
}
class B {
void printB() {
print("B");
}
}
abstract class C {
void printC();
}
// 第一种使用Mixin的方式
class D extends A with B, C {
@override
void printC() {
print("C");
}
void printD() {
print("D");
}
}
// 第二种使用Mixin的方式
// 这种方法无法定义class的实体
// 因为C 是有一个抽象方法,所以定义的E 需要abstract声明
abstract class E = A with B, C;
class E1 extends E {
@override
void printC() {
print("C");
}
void printE() {
print("E");
}
}
D d = new D();
d.printA(); // A
d.printB(); // B
d.printC(); // C
d.printD(); // D
print(d is C); // true
print(d is B); // true
print(d is A); // true
E1 e1 = new E1();
e1.printA(); // A
e1.printB(); // B
e1.printC(); // C
e1.printE(); // E
print(e1 is E); // true
print(e1 is C); // true
print(e1 is B); // true
print(e1 is A); // true
10. 构造函数
- 默认构造函数,默认构造函数没有参数
- 支持命名构造函数;命名构造函数来更清晰的表明你的意图
- 支持常量构造函数;为一个类提供一个状态不变的对象, 且类的所有变量必需声明为 final类型
- 支持工厂方法构造函数;使用factory 来定义 这个构造函数 构造函数执行顺序:
- initializer list(初始化参数列表), 使用逗号分隔初始化表达式。
- superclass’s no-arg constructor(超类的无名构造函数)
- main class’s no-arg constructor(主类的无名构造函数)
命名构造函数
class Person {
String firstName;
// 命名构造函数
Person.fromJson(Map data) {
print('in Person');
}
}
class Employee extends Person {
// 必需调用父类的构造函数
Employee.fromJson(Map data) : super.fromJson(data) {
print('in Employee');
}
}
class Point {
num x;
num y;
Point(this.x, this.y);
// 初始化 x、y 参数列表
Point.fromJson(Map jsonMap)
: x = jsonMap['x'],
y = jsonMap['y'] {
print('In Point.fromJson(): ($x, $y)');
}
}
main() {
var emp = new Employee.fromJson({});
}
常量构造函数
class ImmutablePoint {
final num x;
final num y;
const ImmutablePoint(this.x, this.y);
static final ImmutablePoint origin =
const ImmutablePoint(0, 0);
}
工厂方法构造函数
class Logger {
final String name;
bool mute = false;
// _cache is library-private, thanks to the _ in front
// of its name.
static final Map<String, Logger> _cache =
<String, Logger>{};
factory Logger(String name) {
if (_cache.containsKey(name)) {
return _cache[name];
} else {
final logger = new Logger._internal(name);
_cache[name] = logger;
return logger;
}
}
Logger._internal(this.name);
void log(String msg) {
if (!mute) {
print(msg);
}
}
}
var logger = new Logger('UI');
logger.log('Button clicked');
11. getters and setters方法
- 没有final修饰符的变量,隐含的具有 getter和setter方法
- final修饰符的变量,隐含的具有 getter方法
class Rectangle {
num left;
num top;
num width;
num height;
Rectangle(this.left, this.top, this.width, this.height);
// Define two calculated properties: right and bottom.
num get right => left + width;
set right(num value) => left = value - width;
num get bottom => top + height;
set bottom(num value) => top = value - height;
}
12. 流程控制语句(基本跟其他语言一样)
- 支持if else
- 支持标准的 for 循环
- 对于实现了 Iterable 接口的类,支持 for-in 循环
- 支持While and do-while 循环
- 支持break和continue 终止和继续下一次循环
- 支持switce case语句;每个非空的 case 语句都必须有一个 break 语句
// if else
if (isRaining()) {
you.bringRainCoat();
} else if (isSnowing()) {
you.wearJacket();
} else {
car.putTopDown();
}
// for循环
var message = new StringBuffer("Dart is fun");
for (var i = 0; i < 5; i++) {
message.write('!');
}
// for-in循环
var collection = [0, 1, 2];
for (var x in collection) {
print(x);
}
// while 循环
while (!isDone()) {
doSomething();
}
// do-while 循环
do {
printLine();
} while (!atEndOfPage());
// switce case语句
var command = 'OPEN';
switch (command) {
case 'CLOSED':
executeClosed();
break;
case 'PENDING':
executePending();
break;
default:
executeUnknown();
}
13. 操作符(基本跟其他语言一样)
- 支持 condition ? expr1 : expr2 表达式
- 支持 expr1 ?? expr2; 如果 expr1 是 non-null,返回其值; 否则执行 expr2 并返回其结果
- 支持?.操作符,避免空指针异常
- 级联操作符(..)
- 支持位和移位操作符, &、|、^、~expr、<<、>>
- 支持逻辑操作符,!expr、||、&&
// ?.操作符
var p = new Point(2, 2);
p?.y = 4;
// ?? 操作符
b ??= value; // 如果 b 是 null,则赋值给 b;
// 级联操作符(..)
// 第一个方法 querySelector() 返回了一个 selector 对象。 后面的级联操作符都是调用这个对象的成员, 并忽略每个操作 所返回的值
querySelector('#button') // Get an object.
..text = 'Confirm' // Use its members.
..classes.add('important')
..onClick.listen((e) => window.alert('Confirmed!'));
14. Lists(列表)
Dart 中数组就是 List 对象 简单创建list
var list1 = [1, 2, 3];
assert(list.length == 3);
assert(list[1] == 2);
list[1] = 1;
assert(list[1] == 1);
使用构造函数创建list
var list2 = new List();
list2.add(1);
assert(list2[0] == 1);
15. Map
简单创建 map
var gifts = {
// Keys Values
'first' : 'partridge',
'second': 'turtledoves',
'fifth' : 'golden rings'
};
使用 Map 构造函数创建Map
var gifts = new Map();
gifts['first'] = 'partridge';
gifts['second'] = 'turtledoves';
gifts['fifth'] = 'golden rings';
16. Functions(方法)
- 所有的方法都是Function类型
- 支持高阶函数,可以当作另一个方法的参数
- 如果方法之后一个表达式,可以使用 => expr 语法, 这个 => expr 语法是 { return expr; } 形式的缩写
- 支持闭包,在方法內定义方法
- 支持可选参数,包括可选命名参数和可选位置参数
- 支持默认参数值
- 所有的函数都返回一个值。如果没有指定返回值,则 默认把语句 return null; 作为函数的最后一个语句执行。
// 简单的定义一个方法
bool isNoble(int atomicNumber) {
return _nobleGases[atomicNumber] != null;
}
// => expr表达式用法
// 注意: 在箭头 (=>) 和冒号 (;) 之间只能使用一个 表达式 – 不能使用 语句。 例如:你不能使用 if statement,但是可以 使用条件表达式
bool isNoble(int atomicNumber) => _nobleGases[atomicNumber] != null;
可选命名参数: 在定义方法的时候,使用 {param1, param2, …} 的形式来指定命名参数, 调用方法的时候,你可以使用这种形式 paramName: value 来指定命名参数
// 定义
enableFlags({bool bold, bool hidden}) {
// ...
}
// 定义带有默认值的方法
void enableFlags1({bool bold = false, bool hidden = false}) {
// ...
}
// 使用
enableFlags(bold: true, hidden: false);
可选位置参数:把一些方法的参数放到 [] 中就变成可选 位置参数了
String say(String from, String msg, [String device = 'carrier pigeon', String mood]) {
var result = '$from says $msg';
if (device != null) {
result = '$result with a $device';
}
if (mood != null) {
result = '$result (in a $mood mood)';
}
return result;
}
// 不使用可选参数
say('Bob', 'Howdy'); // Bob says Howdy
// 使用可选参数
say('Bob', 'Howdy', 'smoke signal'); // Bob says Howdy with a smoke signal
17. Exceptions(异常)
- Dart 提供了 Exception 和 Error 类型, 以及一些子类型
- 与java不同,不能在定义方法的时候声明异常, 即Dart 异常是非检查型异常
- 使用 throw 关键词抛出异常, 支持抛出任意的对象
- 使用 try cache finally捕获异常,同时支持用 rethrow 重新抛出异常
try {
// do something
} on Exception catch (e) {
print(e);
// 重新抛出这个异常
rethrow;
} catch (e) {
print(e);
// 抛出任意的对象
throw 'Out of llamas!';
} finally {
print("finally");
}
18. 泛型
// 定义支持的泛型类
abstract class Cache<T> {
T getByKey(String key);
setByKey(String key, T value);
}
// 定义泛型函数
T first<T>(List<T> ts) {
// ...Do some initial work or error checking, then...
T tmp ?= ts[0];
// ...Do some additional checking or processing...
return tmp;
}
19. 枚举类型
- 无法继承枚举类型、无法使用 mix in、无法实现一个枚举类型
- 无法显示的初始化一个枚举类型
enum Color {
red,
green,
blue
}
20. 异步支持
- 支持 async await,(跟es6的async await差不多)
- 使用 Future 或者 Stream执行异步操作
- 支持在循环中使用异步
checkVersion() async {
var version = await lookUpVersion();
if (version == expectedVersion) {
// Do something.
} else {
// Do something else.
}
}
try {
checkVersion();
} catch (e) {
print(e);
}
// 在循环中使用异步
await for (var request in requestServer) {
handleRequest(request);
}
21. Typedefs 给方法类型命名,保留类型信息
typedef int Compare(Object a, Object b);
class SortedCollection {
Compare compare;
SortedCollection(this.compare);
}
// Initial, broken implementation.
int sort(Object a, Object b) => 0;
main() {
SortedCollection coll = new SortedCollection(sort);
assert(coll.compare is Function);
assert(coll.compare is Compare);
}
22. 注释
- 单行注释以 //
- 多行注释以 /* 开始, */ 结尾
- 文档注释可以使用 /// 开始
23. 导包
使用 import 来指定一个库如何使用另外 一个库。
- 对于内置的库,URI 使用特殊的 dart: scheme
- 对于其他的库,你可以使用文件系统路径或者 package: scheme
- 如果两个库具有冲突的标识符,可以使用库的前缀来区分
- 支持导入库的一部分
- 支持延迟载入库
// 导入内置的库
import 'dart:async';
import 'dart:io';
// 导入其他的库
import 'package:flutter/material.dart';
// 使用库的前缀来解决冲突
import 'package:lib1/lib1.dart';
import 'package:lib2/lib2.dart' as lib2;
// Import only foo.
import 'package:lib1/lib1.dart' show foo;
// Import all names EXCEPT foo.
import 'package:lib2/lib2.dart' hide foo;
// 延迟载入库
import 'package:deferred/hello.dart' deferred as hello;
greet() async {
await hello.loadLibrary();
hello.printGreeting();
}