Dart之旅

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类在构造方法上的改进

  1. 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');
  }
}
  1. 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框架。希望我的文章对各位都有帮助,如果有问题可以不吝指教,祝好。

相关推荐
临界点oc33 分钟前
Java面试八股文
java·开发语言·面试
野老杂谈42 分钟前
【面试系列】云计算工程师 高频面试题及详细解答
面试·职场和发展·云计算
Dignity_呱42 分钟前
vue多语言国际化实战
前端·vue.js·面试
LightOfNight2 小时前
【后端面试题】【中间件】【NoSQL】MongoDB的配置服务器、复制机制、写入语义和面试准备
分布式·后端·mongodb·中间件·面试·架构·nosql
慢慢慢时光9 小时前
高阶面试-netty部分
面试
啊猪是的读来过倒14 小时前
Vue 全局状态管理新宠:Pinia实战指南
前端·vue.js·flutter·pinia·全局状态管理
空青72616 小时前
关于日常开发和面试——集合List及数组避坑之一二
java·后端·面试·list·bug·跳槽·改行学it
慢慢慢时光16 小时前
高阶面试-hbase的整理
面试·职场和发展·hbase
Jack轻舟17 小时前
面试必杀技-Java单例模式
java·后端·面试
慢慢慢时光17 小时前
高阶面试-存储系统的设计
面试