Dart的历史
Dart是Google开发的一门编程语言,首次披露是在2011年10月,1.0版本发布在2013年11月14日。2.0在2018年8月发布,增加的主要功能类型系统。3.0在2023年3月发布,增加的主要功能是空安全。软件产品或者技术语言都遵守这个规律,最初都是特别小巧,为了满足用户(这里也包括开发人员),逐渐发展成为全面而庞大的规模。开发语言Java是这样,Python是这样,Dart同样也是这样。我们使用的软件产品同样也遵循这个规律,支付宝是这样,微信也是这样,都想成为超级App,满足用户所有使用场景。
Flutter为什么选择Dart作为开发语言
Dart最开始的愿景是颠覆或者说取代JavaScript,现在作为Flutter的开发语言,Flutter逐渐成为实现了跨平台的功能,不仅可以在IOS,Android,Mac,Desktop(Windows),Linux,以及Web应用开发的全功能的开发平台。Flutter作为跨平台的开发方案的重要选择之一,Dart的优势是不得不提的一个方面。 那为什么要选择 Dart 语言?"Dart团队办公室距离Flutter 团队最近"肯定是其中的一个原因,但是Dart 也为Flutter追求性能和效率的道路提供了大量的帮助,比如AOT编译、Tree Shaking、Hot Reload、多生代无锁垃圾回收,在可维护性和可读性方面同样表现优势。同时选择自己内部开发的语言,会避免因为API之争和Oracle漫长的官司(这是后话,或者是玩笑)。正因为这些特性,Flutter在筛选了多种语言后,最终选择了Dart。
Dart的热重载技术
在开发过程中,快速的开发周期对于迭代是至关重要的。Dart VM提供了一个即时编译器(JIT) ,具有增量重新编译(启用热重载)。Flutter的热重载能够让代码修改运行的速度达到秒级,Flutter热重载技术是使用的Dart在Debug模式下VM直接通过JIT技术直接运行修改的代码(增量编译),数据和状态不会丢失。而Android的Instant Run等相关的热重载技术只能够到几十秒级(分钟级),Android修改Java或者Kotlin代码之后,需要编译字节码,然后通过dx工具生成dex之后才能被Android加载,数据和状态应该会丢失。
Dart语法上的改进
Dart类在构造方法上的改进
- Dart有工厂构造器的概念,使用factory,可以构造类的子类。代码如下:
scala
void main() {
print(Shape.fromTypeName('square'));
print(Shape.fromTypeName('circle'));
}
class Square extends Shape {}
class Circle extends Shape {}
class Shape {
Shape();
factory Shape.fromTypeName(String typeName) {
if (typeName == 'square') return Square();
if (typeName == 'circle') return Circle();
throw ArgumentError('Unrecognized $typeName');
}
}
- Dart还有普通的构造函数和命名的构造函数,创建对象的时候调用构造函数前面的new关键字可以省略。代码如下:
kotlin
class Person {
String name;
int? age;
Person({required this.name, this.age});
Person.defalutName(int this.age): name = "defaultName";
}
Dart的类型推断
Dart有类型推断功能,可以通过把var放在属性名称前面代表一个变量,这种就能推断出属性的类型,这种类型推断不可以改变属性类型,比如说开始赋值为int类型,就不能改变成String类型。 const和final都代表为常量,const代表编译时常量,声明的同时就必须赋值,赋值语句不能是表达式;final代表远行时常量,声明语句和赋值语句可以分开,赋值语句可以是表达式。他们两个只能赋值一次,多次赋值IDE会报错。 Dart有类型推断功能,也有一个动态类型,运行过程中可以改变类型。比如JSON解析中可能不知道具体类型就用dynamic。代码如下:
dart
final userMap = jsonDecode(jsonString) as Map<String, dynamic>;
final user = User.fromJson(userMap);
print('Howdy, ${user.name}!');
print('We sent the verification link to ${user.email}.');
Dart可见性
Dart不像Java一样有public,protected,default,private等多种可见性表示不同作用域的关键字。Dart只有默认public,任何地方都可以使用声明的类或者方法,和在变量名称面前加_表示私有,只能在当前类或者所在文件使用。
Dart空安全
NPE(NullPointerException)是一个非常常见的问题,不仅可以引起应用崩溃,甚至可以引起经济损失。Dart类型分为可空类型和非可空类型,可空类型在类型声明的时候后面加上?,可空类型在方法调用或者属性调用时候也同样需要加上?。不可空类型可以直接调用相应的方法,可空类型需要做判断是否为空的判断,直接调用IDE会报错。可空的范围比不可空的表示的类型范围更广,可以赋值为为null(可以理解为可空类型是不可空类型的父类)。不可空类型如果赋值为null,编译器会报错。方法行参设置为不可空类型,方法调用的时候实参如何设置为null,IDE同样会报错。代码如下:
dart
void main(List<String> args) {
int? age = 10;
print(a.hashCode); //IDE会报错
print('test main');
print(1 is Object);
MyList<String> myList = MyList<String>();
myList.add("132");
myList.add('sdf');
String? name = 'weihaocai';
print(name is Object?);
name = null;
print(name?.length);
print(identical(const Object(), const Object()));
dynamic a = 10;
print('dynamic before is $a');
a = '123';
print('dynamic after is $a is ');
}
Dart常量构造方法
Dart类中可以声明常量构造函数,类的所有属性可以都设置为final,构造方法添加关键字const声明为常量构造函数。代码如下:
dart
class Point {
final int x;
final int y;
const Point({required this.x, required this.y});
}
print(identical(const Point(100, 100), const Point(100, 100))); //此方法调用会返回true
Dart VM帮我们做了优化,如果多次调用同一个类的const 构造函数,他们的参数完全相同,VM不会创建新的对象,而会复用原来已经创建的对象,这样就会使VM中的对象比较少,内存占用比较低,减少GC引发的次数,这样会对Flutter的流畅性和性能有正向作用。
Dart
Dart也是单继承,interface(接口)不能单独设置,后面还需要跟着class,同时还有一个Mixins的概念,可以复用代码和逻辑。代码如下:
arduino
abstract interface class Area {
double area();
}
class Circle implements Area {
final double radius;
Circle(this.radius);
@override
double area() {
return radius * radius * 3.1415926;
}
}
class Rectagle implements Area {
final double width;
final double height;
Rectagle(this.width, this.height);
@override
double area() {
return width * height;
}
}
mixin Swimming {
void swim() => print("Swimming");
bool likesWater() => true;
}
class Duck with Swimming {
final String name;
final String bake;
Duck(this.name, this.bake);
}
Dart单线程模型
Dart的模型是单线程事件驱动的隔离(isolate)。如下图所示:
为了防止主隔离(页面所在的VM)卡顿,我们需要把耗时的任务(网络请求,耗时IO,访问网络,访问数据库,JSON解析等)放到其他隔离运行,然后返回结果。代码如下:
dart
void main() async {
// Read some data.
final jsonData = await Isolate.run(_readAndParseJson);
// Use that data.
print('Number of JSON keys: ${jsonData.length}');
}
总结
总之,Flutter是一个优秀的技术解决方案,值得投入学习。Flutter的优秀离不开Dart的优秀,Flutter是一个在2018年发布的技术产物,现在应该是在快速发展阶段,所以Flutter是一个值得学习的UI框架。希望我的文章对各位都有帮助,如果有问题可以不吝指教,祝好。