《上釉系列-Flutter入门》:Flutter是Google开源的构建用户界面工具包,使用Dart语言便携,本文参考《Flutter开发实战讲解》整理,针对Dart语言与其他常用面向对象编程语言(例如Java)在基础语法上的差异做简单介绍,适读人群为有面向对象语言基础的人。
基础语法
void main(){
print("hello world");
}
作用域:以"_"符号开头的方法或者成员变量表示私有;通过@protected注解标示调用保护的作用
class HelloWorld{
String _privateMember = "文本";
int publicMember = 1;
_privateMethod(){
return 1;
}
publicMethod(){
return 0;
}
@protected
protectedMethod(){
}
}
注释:通过"//"、"///"或者"/****/"标示代码注释,每个语句必须以分号";"结尾,所有对象都继承自Object对象,默认值为null
Setter/Getter
Dart所有的基础类型、类等都继承自Object,Object自带setter/getter方法;如果声明带有final或const则只有一个getter方法
class HelloWorld{
double _ratio;
double get ratio{// Getter重载
//return _ratio;
}
set ratio(double value){// Setter重载
}
}
final/const
使用final或者const声明常量,static const组合代表静态常量,被final/const声明的常量无法修改;const为编译器常量,final为运行时常量;
var x = 1;
final double i = x/0.5;// 运行时常量
const double PI = 3.14;// 编译期常量
import
import关键字用于实现类导入,使用as关键字为导入的类自定义别名
import 'package:flutter/material.dart';
import 'dart:math' as math;// 引入数学常数和函数包,定义别名math
其他dart内置包:dart:io(HTTP和其他IO支持),dart:convert(不同数据表示之间进行转换的编码器和解码器)
基础数据类型
支持数字、字符串、布尔、枚举、数组(列表)、集合和映射等数据类型
数字类型
数字类型包含整型int和浮点型double,整型和浮点型都继承自num类型
int i = 1;// 整型
double j = 1.1;// 浮点型
num x = 2;// 通过num声明为整型
num y = 2.2;// 通过num声明为浮点型
字符串
字符串是一些列的字符文本,可以用""表示,也可以用''表示;支持${expression}表达式,默认对参数调用toString方法,如果添加的是标识符,还可以省略{}符号;支持用+号或者'''进行拼接,但仅支持对字符串与字符串使用+进行拼接。
String name = "GSY";
String tag= 'dart';
// 表达式
int i = 13;
String title = "hello world $name ${1/2}";
// 拼接
String hellWorld = "hello, " + name;
// 长文本
String longString = '''
欲穷千里目,
更上一层楼.
''';
布尔
布尔类型表示为bool,if语句只支持bool类型,不支持直接使用空数据或者整型进行判断
String g = getValue()
// if(g){}/// 不合法判断
if(g!=null){}
枚举
enum UserType{
guest,vip
};
列表类型
也是数组,用List或者[]表示,列表允许存在重复的元素,允许任意数量的空值,每个元素顺序插入;拓展运算符...和空值判断拓展运算符...?(空安全内容)
List list1 = [1,2,3,4];
// 拓展
List list2 = [-1,0,...list1];
// 空安全拓展
List list3 = null;
var list4 = [10,11,...?list3];
集合类型
用Set或者{}表示,不允许存在重复的元素,最多允许一个空值,且无序
Set<String> name = ["hello","world"];
name.add("GSY");
print("length = ${name.length}");
映射类型
用Map或者{}表示,以键值对形式存储元素,键是唯一的,值允许重复
Map map = {"key1":"value1","key2":"value2"};// 声明
map["key1"] = "value3";// 赋值
String value = map["key1"];// 取值
逻辑语句与操作符
常规逻辑语句
常规逻辑语句:if-else switch while
int id = 1;
if(id==1){}else{} // if-else
while(id!=1){} // while
switch(id){ // switch
case 1:
break;
case 2:
break;
default:
}
三目运算符
逻辑判断并返回判断结果
int id = 1;
String result = (id>1) ? "大于1" : "小于等于1";
级联运算符
级联运算符可以对类的内部成员进行链式调用
Event event = Event();
event
..id = 1
..type = ""
..actor = "";
空安全及其他运算符
赋值运算符?? ??= ~/ 以及判空运算符?
AA ?? "999"; // 如果AA为空则返回999
AA ??= "999"; // 如果AA为空则将AA赋值为999
AA ~/ 999 // AA对于999整除
Event event = Event()
event?.fix(); // 如果event为空,则不执行fix
操作符重载
class Vector{
final int x,y;
Vector(this.x, this.y);
Vector operator +(Vector v) => Vector(x+v.x, y+v.y);
}
void main(){
final v = Vector(1,1);
final w = Vector(2,2);
final result = v + w;
}
支持重载的操作符:<、>、<=、>=、-、+、/、~/、*、%、|、^、&、<<、>>、[]、[]=、~、==
var与dynamic
var声明变量,编译期语法糖,会自动推到出数据类型;var声明未指定类型和赋值时则为dynamic
dynamic声明表示动态类型,编译后是一个object类型,编译期不进行检查,运行时检查。
var i;// i为dynamic类型
init(){
i = "";
i++;
}
函数方法
函数类型:参数类型可以指定或不指定
可选参数及默认值:可选参数通过{}符号包裹,调用时传递时需要指定参数名称
method(String name, reposName, {branch = "master"}){} // 方法声明
method("aaa", "bbb", brach = "dev") // 方法调用
方法作为参数传递
void main(){
call(String name){
return "hello $name";
}
method(call);
}
method(String call(String name)){
print(call("GSY"));
}
类、接口和继承
使用implements继承实现,可以实现多个接口,然后复写父类方法
abstract class Interface{
void doA();// 抽象类可以只声明不实现方法
}
class InterfaceClass{
void doB(){}//
}
class Name implements Interface,InterfaceClass{
@override
void doA(){ // 复写方法
}
@override
void doB(){
}
}
类的call方法:类默认都实现call()方法
方法的call方法:typedef声明定义的方法可以使用方法的call方法
class CallObject{ // 类声明
call(String name) => "hello $name"; // call方法
}
typedef void HelloMethod(String name);
HelloMethod hm = (String name){
Print("hello $name");
}
init(){
CallObject callObject = CallObject();
callObject?.call("GSY");
hm("GSY"); // 直接通过函数方式调用
hm?.call("GSY"); // 通过call方式调用方法
}
mixins
混入模式,混入时的基础顺序为从右到左一次执行,并且和super方法是否执行有关
如果方法冲突,则实际调用的方法为按照extends、mixins和implements的顺序查找对应的方法
abstract class Base{
a(){}
}
class A extends Base{
b(){}
}
class B extends Base{
c(){}
}
class A2 extends Base{
b(){}
}
class M exnteds B with A,A2{}
// M的a()实际调用A2的(实际为Base的),b()实际调用A2的,c()实际调用B的
构造方法
默认构造方法只有一个,可以通过不同成员变量数量初始化,或者通过自定义构造函数名称实现
class A{
String name;
A(){}
A(this.name){}
A.empty(){}
A.withName(String name){
this.name = name;
}
}
异常处理
通过继承Exception声明异常,通过throw主动抛出异常,通过try-catch捕获异常,通过finally进行全局的最终处理
try{
...
throw CustomException();
}on CustomException catch(customException){
}on FormatException catch(formatException){
}finally{
}
常见异常:FormatException、IoException、IsolateSpawnException、Timeout
Isolate
在单线程模式中增加Isolate提供跨线程的真异步操作,isolate之间的数据只能通过port的端口方式进行发送;可以通过compute的封装接口,方便isolate的快速调用。
isolate用于执行上下文隔离;ReceivePort与SendPort一起,是唯一的通信方式;SendPort将消息发送到其他ReceivePort。
Isolate isolate;
void doIsolate() async{
var receive = ReceivePort();
isolate = await Isolate.spawn(echoResult, receive.sendPort);
receive.listen((data){
});
}
void echoResult(SendPort port){
final msg = "do you know me";
Timer.periodic(const Duration(seconds: 1),(_){
port.send(msg);
});
}
void kill(){
isolate?.kill(priority: Isolate.immediate);
isolate=null;
}
Zone
通过Zone表示指定的代码执行环境
runZoned((){}, onError: (Objects obj, StackTrace stack){});
异步执行
支持async/await表示异步执行,属于语法糖,实际通过Future对象执行;有别于Isolate执行,属于假异步的实现逻辑
request() async{
await Future.delayed(Duration(seconds: 1));
return "data";
}
doSomeThing() async{
String data = await request();
return "packaged $data";
}
void main(){
doSomeThing().then((data){
print("data: $data");
});
}
拓展方法
向任何类型添加新功能,big具有常规方法调用的简洁性和自动完成性
extension ExxtendsFunc on String{
int parseInt(){
return int.parse(this);
}
double parseDouble(){
return double.parse(this);
}
}
void main(){
int i = "42".parseInt();
double d = "43.2".parseDouble();
}