Flutter(三)——一篇文章掌握Dart语言的用法(三)

简介: Flutter(三)——一篇文章掌握Dart语言的用法(三)

异步编程


Dart语言和JavaScript语言的共同点是单线程,同步代码会阻塞程序,因此程序里能看到大量的异步操作,它是用Future对象来执行相关操作的,并且async函数使用await关键字时才被执行,直到一个Future操作完成,Future支持链式操作的方式,可以按顺序执行异步操作。


Future是什么?

一个Future是一个Future自身的泛型Flutter对象,它表示一个异步操作产生的T类型的结果,如果结果的值不可用,Future的类型会是Future,如果返回一个Future的函数被调用了,将会发生以下两件事:


(1)这个函数加入待完成的队列并且返回一个未完成的Future对象


(2)当这个操作结束了,Future对象返回一个值或者错误。


例如:


Future<int> future=getFuture();
future.then((value)=>handleValue(value))
  .catchError((error)=>handleError(error))
  .whenComplete()=>handlerComplete();


如果你是前端的开发人员,可以理解Future类似前端里的Promise。我们在future.then中接收异步处理结果,并根据业务需求做相应的处理。而future.catchError则用于在异步函数中捕获并处理错误。在有些业务场景下,无论是异步任务的处理结果是成功还是失败,我们都需要再进行一些处理,这时候可以使用Future的whenComplete进行回调。


async和await

当遇到需要延迟的运算(async)时,将其放到延迟运算的队列(await)中去,把不需要延迟的运算的部分先执行完,最后在来处理延迟的运算部分。但是,要使用await,就必须在有async标记的函数中运行,否则这个await会报错。


其实这个和JavaScript也很像,async和await是Future的语法糖(Syntacticsugar),解决了回调地狱(Callback Hell)的问题。


那么回调地狱又是什么?这个需要结合具体业务场景来说,比如“业务1->业务2->业务3”,这三个任务都是异步的,那么业务1成功之后调用业务1的then回调,然后业务1的then里面在调用业务2,依次类推,就形成了回调地狱。回调地狱多了之后,我们的代码会非常难看,因为需要大量的缩进,比如这种:

step1('step1').then(step1Result(){
  step2('step2').then(step2Result(){
  step3('step3').then(step3Result(){
    //依次类推456....
  })
  })
})


我们刚在上面讲解了async和await是Future的语法糖,我们在使用过程中给人的感觉是在调用同步的代码。为了解决这种回调地狱,我们对以上代码结构进行了一些调整,修改后的代码如下:

steps() async{
  try{
  String step1Result=await step1('step1');
  String step2Result=await step2(step1Result);
  String step3Result=await step3(step2Result);
  //456......
  }catch(e){
  print(e);
  }
}


从上面的代码我们可以看到,await必须被包裹在async里面,如果没有async就会报错。后续我们将通过其他章节在进行详细的使用。


继承,接口实现

在Dart语言中,继承和接口实现基本上与Java类似,但是我们需要注意以下几点:


(1)继承:构造函数不能被继承,而且在Dart语言中,没有Java中的公有与私有的修饰符,因此,可以直接访问超类中的所有变量与方法。


(2)接口实现:在Dart语言中,没有接口的修饰符,但是每个类都是一个隐式的接口,这个接口包含类里的所有成员变量与方法,当类被当作接口使用的时候,类中的方法就是接口中的方法,它需要在子类里重新被实现,而且实现的时候需要加上@override关键字。


使用方式如下:

abstract class A{
  void printA();
}
class B{
  void printB(){
  }
}
class C{
  void printC(){
  print('C');
  }
}
class SoftwareSngineer extends C implements A,B{
  @override
  void printA{
  //重写
  }
  @override
  void printB(){
  //重写
  }
}


混合

在Dart语言中,我们有一个新的特性,那就是混合的语言特性mixins,它的作用是在类中混入其他功能,mixins最早出现在Lisp语言中。你可以这么来理解,就是在面向对象的语言中,mixins是一个可以把自己的方法提供给其他类使用,但却不需要成为其他类的父类的类,它以非继承的方式来复用类中的代码。要使用mixins,则要用关键字with来复用类中的代码,使用方式如下:

abstract class A{
    factory A._(){
        return null;
    }
    void printA(){
        print('A');
    }
}
class C with A{
    @override
    void printA(){
        print('A');
    }
}
void main(){
    C()..printA();
}


那我们现在就有一个疑问了,如果同时使用继承,接口实现与混合,并且@override的方法都一样,那么执行的优先级会怎么样?我们直接上代码跑一下就清楚了:

class Cat{
    void show(){
        print('小猫');
    }
}
class Brid{
    void show(){
        print('小鸟');
    }
}
class Owner{
    void show(){
        print('主人');
    }
}
class person1 extends Owner with Cat,Brid{
    void show(){
        print('主人1养了猫和鸟');
    }
}
class person2 extends Owner with Cat implements Brid{
    void show(){
        print('主人2养了猫和鸟');
    }
}
void main(){
    person1()..show();
    person2()..show();
}


如果代码如上,没有任何注释,那么会直接执行类本身的方法,输出效果如下:


现在我们注释调用两个person中的方法,其他代码不变:


class person1 extends Owner with Cat,Brid{
    //void show(){
        //print('主人1养了猫和鸟');
    //}
}
class person2 extends Owner with Cat implements Brid{
    //void show(){
        //print('主人2养了猫和鸟');
    //}
}


那么现在打印出来的效果就是这样:


从这里我们可以看出来,假如使用了混合,继承与接口实现,那么它的执行优先级顺序是mixins->extends->implements。


泛型

在Dart语言中,泛型与Java中很相似,比如List。用尖括号括起来的就是泛型的写法。在List中,这个E代表泛型的类型,且不一定要用E表示,还可以用T,S,K等表示,我们先来简单的使用一下:

void main(){
  List animals=new List<String>();
  animals.addAll('小猫','小狗','小兔');
}


在上面代码中,我们使用了List集合来存储小动物,并且指定了List泛型,这样定义就说说明只能存储字符串类型。


Dart语言基础就这么多,重点都在后面,前面大部分只要学过其他的语言,看看根本不费劲,Dart语言是Flutter开发的主要语言,必须要掌握的哦。

相关文章
|
2月前
|
Dart
如何在 Flutter 项目中使用 Dart 语言?
如何在 Flutter 项目中使用 Dart 语言?
127 58
|
13天前
|
容器
Flutter &&鸿蒙next中的 Stack 和 Positioned 用法详解
在 Flutter 中,Stack 和 Positioned 是创建层叠布局和灵活定位元素的常用组件。Stack 可以将多个子组件叠加在一起,允许子组件相互重叠;Positioned 用于在 Stack 内部精确控制子组件的位置。本文详细介绍了它们的基本用法、属性和应用场景,包括动画、弹出层和悬浮按钮等。
63 1
|
18天前
|
Dart
flutter dart mixin 姿势
flutter dart mixin 姿势
|
15天前
|
Dart 安全 编译器
Flutter结合鸿蒙next 中数据类型转换的高级用法:dynamic 类型与其他类型的转换解析
在 Flutter 开发中,`dynamic` 类型提供了灵活性,但也带来了类型安全性问题。本文深入探讨 `dynamic` 类型及其与其他类型的转换,介绍如何使用 `as` 关键字、`is` 操作符和 `whereType&lt;T&gt;()` 方法进行类型转换,并提供最佳实践,包括避免过度使用 `dynamic`、使用 Null Safety 和异常处理,帮助开发者提高代码的可读性和可维护性。
67 1
|
1月前
|
Dart 开发者 Windows
flutter:dart的学习
本文介绍了Dart语言的下载方法及基本使用,包括在Windows系统上和VSCode中的安装步骤,并展示了如何运行Dart代码。此外,还详细说明了Dart的基础语法、构造函数、泛型以及库的使用方法。文中通过示例代码解释了闭包、运算符等概念,并介绍了Dart的新特性如非空断言操作符和延迟初始化变量。最后,提供了添加第三方库依赖的方法。
28 12
|
3月前
|
Dart 前端开发 JavaScript
Flutter&Dart-异步编程Future、Stream极速入门
Flutter&Dart-异步编程Future、Stream极速入门
72 4
Flutter&Dart-异步编程Future、Stream极速入门
|
3月前
|
Dart JavaScript 前端开发
Dart或Flutter中解决异常-type ‘int‘ is not a subtype of type ‘double‘
Dart或Flutter中解决异常-type ‘int‘ is not a subtype of type ‘double‘
128 4
|
3月前
|
Dart 开发工具
消除Flutter doctor的警告Warning: `dart` on your path resolves to xxx/bin/dart
消除Flutter doctor的警告Warning: `dart` on your path resolves to xxx/bin/dart
66 0
|
存储 缓存 Dart
[Flutter]足够入门的Dart语言系列之面向对象:类成员的可见性、常量和工厂构造函数详解
类和成员的可见性,这在基于库或包的开发中非常重要,Dart中提供了工厂构造函数,可以方便的实现单例、缓存实例对象、返回子类等,以及常量构造函数的使用......
299 0
[Flutter]足够入门的Dart语言系列之面向对象:类成员的可见性、常量和工厂构造函数详解
|
Dart
[Flutter]足够入门的Dart语言系列之函数:函数定义、调用、5种参数类型和main函数
函数(Function)也被称为方法(Method)。其最直观的理解就是数据中的函数,比如y=f(x),在编程中,f对输入x进行处理,返回结果y,就是一个函数......
1024 0
[Flutter]足够入门的Dart语言系列之函数:函数定义、调用、5种参数类型和main函数