想学Flutter,就请关注这个专栏
Flutter系列(一)——详细介绍javaFlutter系列(二)——与React Native进行对比
git
文档归档:
github.com/yang0range/…async
在上一篇文章,咱们详细的介绍了Dart语法的一些基本语法,这一这篇文章,咱们继续介绍Dart的语法的相关知识。ide
不论是Java语言仍是Dart语言,都有异常,以及异常的捕获,可是不一样的是dart中的异常都是非检查异常,方法能够不声明可能抛出的异常,也不要求捕获任何异常。函数
Dart提供了Exception和Error类型以及一些子类型来定义异常。不过,还能够自定义异常,只要抛出非空对象做为异常便可,不要求必须是Exception和Error对象,可是通常来讲都是抛出Exception和Error类型。post
接下来咱们详细介绍一下。
异常的抛出和Java仍是很相像的。
//抛出Exception对象
throw new FormatException('格式异常');
//抛出Error对象
throw new NullThrownError();
//抛出任意非null对象
// throw '这是一个异常';
复制代码
try { throw new NullThrownError();
// throw new OutOfMemoryError();
} on OutOfMemoryError {
//on 指定异常类型
print('没有内存了');
// rethrow; //把捕获的异常给 从新抛出
} on Error {
//捕获Error类型
print('Unknown error catched');
} on Exception catch (e) {
//捕获Exception类型
print('Unknown exception catched');
} catch (e, s) {
//catch() 能够带有一个或者两个参数, 第一个参数为抛出的异常对象, 第二个为StackTrace对象堆栈信息
print(e);
print(s);
}
}
复制代码
类的概念和Java当中相似。
可是也有很大的区别。
//java中写法
class P {
double x;
double y;
P(int x, int y) {
this.x = x;
this.y = y;
}
}
//dart建议写法
class P {
num x;
num y;
Point(this.x, this.y);
复制代码
class P {
num x;
num y;
Point(this.x, this.y);
//重定向构造函数,使用冒号调用其余构造函数
P.alongXAxis(num x) : this(x, 0);
}
复制代码
class Rectangle {
num left;
num top;
num width;
num height;
Rectangle(this.left, this.top, this.width, this.height);
num get right => left + width;
set right(num value) => left = value - width;
num get bottom => top + height;
set bottom(num value) => top = value - height;
}
复制代码
Mixins是Dart里面的一个全新概念,简单来讲,用来复用多个类之间的代码,减小耦合,换句话来讲,能够从中扩展方法(或变量)而不扩展类。
不用不知道,一用起来才发现,真香!
下面具体举例说明一下:
例如,咱们有这么一个职业关系图:
从图中能够梳理出如下关系:
若是咱们用Java来实现的花
//工做者
abstract class Worker {
public abstract void doWork();//工做者须要工做
}
//工程师
class Engineer extends Worker {
@Override
public void doWork() {
System.out.println("工程师在工做");
}
}
//教师
class Teacher extends Worker {
@Override
public void doWork() {
System.out.println("教师在教学");
}
}
//软件工程师
class SoftwareEngineer extends Engineer {
}
//建筑工程师
class BuildingEngineer extends Engineer {
}
//美术教师
class ArtTeacher extends Teacher {
}
//IT教师
class ITTeacher extends Teacher {
}
复制代码
若是用Dart来实现
//工做者
abstract class Worker {
void doWork();//工做者须要工做
}
//工程师
class Engineer extends Worker {
void doWork() {
print('工程师在工做');
}
}
//教师
class Teacher extends Worker {
void doWork() {
print('教师在教学');
}
}
//软件工程师
class SoftwareEngineer extends Engineer {
}
//建筑工程师
class BuildingEngineer extends Engineer {
}
//美术教师
class ArtTeacher extends Teacher {
}
//IT教师
class ITTeacher extends Teacher {
}
复制代码
从以上来看,彷佛Java和Dart没有什么特别大的区别,由于Dart也是单继承。
下面,咱们再把场景丰富一下。
经过图形或表格能够看出,软件工程师和IT教师都具有修电脑的能力,建筑工程师和美术教师都具有手绘的能力,可是这些能力都是他们特有的,不是工程师或者教师具有的能力,因此不能在他们的父类中实现。
若是使用Java,那么咱们天然就想到了使用interface。
interface CanFixComputer {
void fixComputer();
}
interface CanDesignSoftware {
void designSoftware();
}
//软件工程师
class SoftwareEngineer extends Engineer implements CanFixComputer, CanDesignSoftware {
@Override
public void fixComputer() {
System.out.println("修电脑");
}
@Override
public void designSoftware() {
System.out.println("设计软件");
}
}
//IT教师
class ITTeacher extends Teacher implements CanFixComputer {
@Override
public void fixComputer() {
System.out.println("修电脑");
}
}
复制代码
可是,咱们知道Dart当中没有interface的概念,但并不意味着这门语言没有接口,事实上,Dart任何一个类都是接口,你能够实现任何一个类,只须要重写那个类里面的全部具体方法。
若是要用Dart来实现的化,只须要将interface修改为abstract class。
可是咱们发现,fixComputer这个接口被继承了两次,而且两次的实现都是同样的,这里就出现了代码重复和冗余的问题。怎么办呢?在java中咱们有接口的default实现来解决这个问题(这是一个java8出现的不得已的方案。)
可是,有了mixins以后,这件事就变得不那么难了。
abstract class CanFixComputer {
void fixComputer() {
print('修电脑');
}
}
abstract class CanDesignSoftware {
void designSoftware() {
print('设计软件');
}
}
//软件工程师
class SoftwareEngineer extends Engineer
with CanFixComputer, CanDesignSoftware {
}
//IT教师
class ITTeacher extends Teacher with CanFixComputer {
}
main() {
ITTeacher itTeacher = new ITTeacher();
itTeacher.doWork();
itTeacher.fixComputer();
SoftwareEngineer softwareEngineer = new SoftwareEngineer();
softwareEngineer.doWork();
softwareEngineer.fixComputer();
softwareEngineer.designSoftware();
}
复制代码
经过以上代码,咱们能够看到这里不用implements,更不是extends,而是with。
每一个具备某项特性的类再也不须要具体去实现一样的功能,接口是无法实现功能的,而经过继承的方式虽然能实现功能,但已经有父类,同时不是一个父类,又不能多继承,因此这个时候,Dart的Mixin机制就比Java的接口会高效,开发上层的只须要关心当前须要什么特性,而开发功能模块的关心具体要实现什么功能。
关于顺序的理解
既然是with,那应该也会有顺序的区别。
class First {
void doPrint() {
print('First');
}
}
class Second {
void doPrint() {
print('Second');
}
}
class Father {
void doPrint() {
print('Father');
}
}
class Son1 extends Father with First,Second {
void doPrint() {
print('Son1');
}
}
class Son2 extends Father with First implements Second {
void doPrint() {
print('Son2');
}
}
main() {
Son1 son1 = new Son1();
son1.doPrint();
Son2 son2 = new Son2();
son2.doPrint();
}
复制代码
输出的内容是:
Son1
Son2
复制代码
经过这里,咱们能够看到
能够看到,不管是extends、implements仍是mixin,优先级最高的是在具体类中的方法。
下一个例子:
class First {
void doPrint() {
print('First');
}
}
class Second {
void doPrint() {
print('Second');
}
}
class Father {
void doPrint() {
print('Father');
}
}
class Son1 extends Father with First,Second {
}
class Son2 extends Father with First implements Second {
}
main() {
Son1 son1 = new Son1();
son1.doPrint();
Son2 son2 = new Son2();
son2.doPrint();
}
复制代码
输出的结果:
Second
First
复制代码
其实在Son2中implements只是说要实现他的doPrint()方法,这个时候其实具体实现是First中Mixin了具体实现。
而Mixin的具体顺序也是能够从代码倒过来看的,最后mixin的优先级是最高的。
在Dart当中,有不少的容器对象,在建立对象时均可以定义泛型类型,这一点和Java是同样的。
例如:
var list = List<String>();
list.add('aaa');
list.add('bbb');
list.add('ccc');
print(list);
var map = Map<int, String>();
map[1] = 'aaaa';
map[2] = 'bbbb';
map[3] = 'cccc';
print(map);
复制代码
和Java的区别
说到异步就不得不说到Future。
Future与JavaScript中的Promise很是类似,表示一个异步操做的最终完成(或失败)及其结果值的表示。简单来讲,它就是用于处理异步操做的,异步处理成功了就执行成功的操做,异步处理失败了就捕获错误或者中止后续操做。一个Future只会对应一个结果,要么成功,要么失败。
由于Flutter返回的都是一个Fluter对象,天然就能够采用链式方法。
若是业务逻辑中有大量异步依赖的状况,将会出现上面这种在回调里面套回调的状况,过多的嵌套会致使的代码可读性降低以及出错率提升,而且很是难维护,这个问题被形象的称为回调地狱(Callback Hell)。
这个问题在JS当中十分的突出,Dart几乎是一样的问题,而后把相关方法平移过来。因此功能和用法也几乎是相同的。
Stream 也是用于接收异步事件数据,和Future 不一样的是,它能够接收多个异步操做的结果(成功或失败)。 也就是说,在执行异步任务时,能够经过屡次触发成功或失败事件来传递结果数据或错误异常。 Stream 经常使用于会屡次读取数据的异步任务场景,如网络内容下载、文件读写等。
Stream.fromFutures([
// 1秒后返回结果
Future.delayed(new Duration(seconds: 1), () {
return "hello 1";
}),
// 抛出一个异常
Future.delayed(new Duration(seconds: 2),(){
throw AssertionError("Error");
}),
// 3秒后返回结果
Future.delayed(new Duration(seconds: 3), () {
return "hello 3";
})
]).listen((data){
print(data);
}, onError: (e){
print(e.message);
},onDone: (){
});
复制代码
输出
I/flutter (17666): hello 1
I/flutter (17666): Error
I/flutter (17666): hello 3
复制代码
全部Dart代码都在隔离区内运行,而不是线程。每一个隔离区都有本身的内存堆,确保不会从任何其余隔离区访问隔离区的状态。
经过这三篇文章,咱们基本上把Dart语言的所涉及,所涵盖的内容都讲述了一遍。
这些仍是偏理论多一些,语法仍是在多实践,多写,多练的过程中来找到其中的真谛。
接下来,咱们就开始详细的展开Flutter的介绍了!
Flutter已是Top20的软件库,经过接下来的一系列的文章,但愿我和你们一块儿来学习Flutter,一块儿进步,一块儿有所收获,掌握将来技术主流的主动权!
有什么好的建议,意见,想法欢迎给我留言!
kevinwu.cn/p/ae2ce64/
www.jianshu.com/p/06604077d…《Flutter实战》