Flutter 入门教程——Dart语言介绍

故事扮演 提交于 2019-12-02 05:55:11

目录

介绍

Dart vs Java

一、异步

1、Future

2、Async/await

3、Stream

二、变量声明

1、var

2、final和const

3、dynamic和Object


介绍

Dart 是谷歌开发的计算机编程语言 ,被用于web、服务器、移动端和物联网等领域的开发。Dart是面向对象的、类定义的、单继承的语言。语法类似C语言和JavaScript,支持接口(interfaces)、混入(mixins)、抽象类(abstract classes)、具体化泛型(reified generics)、可选类型(optional typing) 。

2011年10月10至12日Dart在丹麦奥尔胡斯举行的GOTO大会上亮相。由Lars bak和kasper lund创建。

2015年5月Dart开发者峰会上,亮相了基于Dart语言的移动应用程序开发框架 Sky ,后更名为 Flutter。

Dart vs Java

在VM性能层面,Dart VM在内存回收和吞吐量都进行了反复的优化,因此,Dart在Flutter中可以将GC做到10ms以内。毕竟Google在Go(没用VM但有GC)、JavaScript(v8)、Dalvik(Android上的Java VM)上已经有了很多技术积淀。Dart和Java相比,决胜因素并不会是在性能方面。

在语法层面,Dart要比Java更有表现力。Dart的设计应该是同时借鉴了Java和JavaScript。Dart在静态语法方面和Java非常相似,如类型定义、函数声明、泛型等,而在动态特性方面又和JavaScript很像,如函数式特性、异步支持等。除了融合Java和JavaScript语言之所长之外,Dart也具有一些其它具有表现力的语法,如可选命名参数、..(级联运算符)和?.(条件成员访问运算符)以及??(判空赋值运算符)。

Dart目前真正的不足是生态,但笔者相信,随着Flutter的逐渐火热,会回过头来反推Dart生态加速发展,对于Dart来说,现在需要的是时间。

 

一、异步

1、Future

Future与JavaScript中的Promise非常相似,一个异步操作的最终完成或失败及其结果值(一个Future只会对应一个结果,要么成功,要么失败)。

(1)Future.then

Future.deleyed()进行延迟2秒后打印data:

Future.delayed(new Duration(seconds: 2),(){
   return "hi world!";
}).then((data){
   print(data);
});

(2)Future.catchError

如果异步任务发生错误,在catchError中捕获错误:

Future.delayed(new Duration(seconds: 2),(){
   throw AssertionError("Error");  
}).then((data){
   //成功
   print("success");
}).catchError((e){
   //失败
   print(e);
});

then方法还有一个可选参数onError,我们也可以它来捕获异常:

Future.delayed(new Duration(seconds: 2), () {
    throw AssertionError("Error");
}).then((data) {
    print("success");
}, onError: (e) {
    print(e);
});

(3)Future.whenComplete

有时网络请求前需要弹加载框,请求结束使用FuturewhenComplete回调进行关闭:

Future.delayed(new Duration(seconds: 2),(){
   throw AssertionError("Error");
}).then((data){
   //成功 
   print(data);
}).catchError((e){
   //失败
   print(e);
}).whenComplete((){
   //请求结束
});

(4)Future.wait

有些时候需要从多个网络接口获取数据,获取成功后将进行特定的处理后再显示到UI界面上。此时应该使用Future.wait,在Future数组中执行所有Future对象都成功后,才会触发then的成功回调,只要有一个Future执行失败,就会触发catchError错误回调。代码如下:

Future.wait([

  Future.delayed(new Duration(seconds: 2), () {
    return "hello";
  }),

  Future.delayed(new Duration(seconds: 4), () {
    return " world";
  })
]).then((results){
  print(results[0]+results[1]);//4秒后显示 hello world
}).catchError((e){
  print(e);
});

2、Async/await

Dart中的async/await 和JavaScript中的async/await功能和用法是一模一样的。

回调地狱(Callback Hell):如果出现大量异步任务依赖其它异步任务的结果时,必然会出现Future.then回调中套回调情况。比如,用户先登录,登录成功后会获得用户ID,通过用户ID,请求用户信息,获取到用户个人信息后,保存在本地。

//先分别定义各个异步任务
Future<String> login(String userName, String pwd){
    ...
    //用户登录
};
Future<String> getUserInfo(String id){
    ...
    //获取用户信息 
};
Future saveUserInfo(String userInfo){
    ...
    // 保存用户信息 
};

login("1","1").then((id){
 //登录成功后通过,id获取用户信息    
 getUserInfo(id).then((userInfo){
    //获取用户信息后保存 
    saveUserInfo(userInfo).then((){
       //保存用户信息,接下来执行其它操作
    });
  });
})

这种在回调里面套回调会导致的代码可读性下降以及出错率提高,并且非常难维护,这个问题被形象的称为回调地狱(Callback Hell)。回调地狱问题在之前JavaScript中非常突出,也是JavaScript被吐槽最多的点,但随着ECMAScript6和ECMAScript7标准发布后,这个问题得到了非常好的解决,而解决回调地狱的两大神器正是ECMAScript6引入了Promise,以及ECMAScript7中引入的async/await。 而在Dart中几乎是完全平移了JavaScript中的这两者:Future相当于Promise,而async/await连名字都没改。

(1)使用Future消除Callback Hell

login("alice","******").then((id){

    return getUserInfo(id);

}).then((userInfo){

    return saveUserInfo(userInfo);

}).then((e){
   
}).catchError((e){
  print(e);
});

Future 的所有API的返回值仍然是一个Future对象,所以可以进行链式调用 。

(2)使用async/await消除callback hell

通过Future回调中再返回Future的方式虽然能避免层层嵌套,但是还是有一层回调。使用async/await能够让我们可以像写同步代码那样来执行异步任务而不使用回调的方式。

task() async {
   try{
    String id = await login("alice","******");
    String userInfo = await getUserInfo(id);
    await saveUserInfo(userInfo);
    //执行接下来的操作   
   } catch(e){
    //错误处理   
    print(e);   
   }  
}
  • async :表示函数是异步,定义的函数返回一个Future对象,可以使用then方法添加回调函数。
  • await  :表示等待该异步任务完成;await必须出现在 async 函数内部。

其实,无论是在JavaScript还是Dart中,async/await都只是一个语法糖,编译器或解释器最终都会将其转化为一个Promise(Future)的调用链。

 

3、Stream

Stream 也是用于接收异步事件数据,和 Future.wait 不同的是,它可以接收多个异步操作的结果。 也就是说,在执行异步任务时,可以通过多次触发成功或失败事件来传递结果数据或错误异常。 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: (){

});

二、变量声明

1、var

它可以接收任何类型的变量,但最大的不同是Dart中var变量一旦赋值,不能再改变其类型,如:

var t;
t = "hi world";
// 下面代码在dart中会报错,因为变量t的类型已经确定为String,
t = 1000;

2、finalconst

常量声明用 final 或 const 修饰符。常量只能赋值置一次。两者区别在于:const 变量是一个编译时常量,final变量在第一次使用时被初始化。被final或者const修饰的变量,变量类型可以省略,如:

//可以省略String这个类型声明
final str = "hi world";
//final String str = "hi world"; 
const str1 = "hi world";
//const String str1 = "hi world";

3、dynamicObject

Object 是Dart所有对象的根基类,也就是说所有类型都是Object的子类(包括Function和Null),所以任何类型的数据都可以赋值给Object声明的对象。 dynamicvar一样都是关键词,声明的变量可以赋值任意对象。 而dynamicObject相同之处在于,他们声明的变量可以在后期改变赋值类型

 dynamic t;
 Object x;
 t = "hi world";
 x = 'Hello Object';
 //下面代码没有问题
 t = 1000;
 x = 1000;

dynamicObject不同的是,dynamic声明的对象编译器会提供所有可能的组合, 而Object声明的对象只能使用Object的属性与方法,,否则编译器会报错。如:

 dynamic a;
 Object b;
 main() {
     a = "";
     b = "";
     printLengths();
 }   

 printLengths() {
     // no warning
     print(a.length);

     // warning:The getter 'length' is not defined for the class 'Object'
     print(b.length);
 }

结束。谢谢!


参考 https://book.flutterchina.club/chapter1/dart.html

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!