Flutter基础 -- Dart 语言 -- 进阶使用

2024-06-03 12:36

本文主要是介绍Flutter基础 -- Dart 语言 -- 进阶使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

1. 泛型 generics

1.1 泛型使用

1.2 泛型函数

1.3 构造函数泛型

1.4 泛型限制

2. 异步 async

2.1 异步回调 then

2.2 异步等待 await

2.3 异步返回值

3. 生成器 generate (了解)

3.1 同步生成器 sync*

使用 sync* 的场景

总结

3.2 异步生成器 async*

使用 StreamSubscription 的优势

3.3 递归生成器 sync*

4. 类型定义 typedef

4.1 typedef 定义使用

4.2 简化常用类型定义

5. 空安全

5.1 默认不可空

5.2 type? 可空

5.3 value! 值保证不为空,主观上

5.4 value?. 不为空才执行

5.5 value?? 如果空执行

5.6 late 声明

5.7 late 类成员延迟初始

5.8 List、泛型

5.9 Map

6. 扩展 extension

6.1 示例 扩展日期时间

6.2 业务场景


1. 泛型 generics

1.1 泛型使用

main(List<String> args) {var l = <String>[];l.add('aaa');l.add('bbb');l.add('ccc');print(l);var m = <int, String>{};m[1] = 'aaaa';m[2] = 'bbbb';m[3] = 'cccc';print(m);
}[aaa, bbb, ccc]
{1: aaaa, 2: bbbb, 3: cccc}

容器对象,在创建对象时都可以定义泛型类型

1.2 泛型函数

K addCache<K, V>(K key, V val) {print('$key -> $val');return val;
}main(List<String> args) {var key = addCache('url', 'https://wiki.doucafecat.tech');print(key);
}url -> https://wiki.doucafecat.tech
https://wiki.doucafecat.tech

1.3 构造函数泛型

class Phone<T> {final T mobileNumber;Phone(this.mobileNumber);
}main(List<String> args) {var p = Phone<String>('ducafecat');print(p.mobileNumber);
}ducafecat

这是大多数情况下使用泛型的场景,在一个类的构造函数中(Phone是一个泛型类)

(就是cpp的template)

1.4 泛型限制

定义

class AndroidPhone {void startup() {print('Android Phone 开机');}
}class Phone<T extends AndroidPhone> {final T mobile;Phone(this.mobile);
}

实例

main(List<String> args) {var ad = AndroidPhone();var p = Phone<AndroidPhone>(ad);p.mobile.startup();
}Android Phone 开机

通过 extends 关键字 可以限定你可以泛型使用的类型

通过 class Phone<T extends AndroidPhone> {

就可以让传入的实参必须是 AndroidPhone类型 或者 是 AndroidPhone类型的子类

2. 异步 async

2.1 异步回调 then

import 'package:dio/dio.dart';void main() {Dio dio = Dio();dio.get("https://wpapi.ducafecat.tech/products/categories").then((response) {print(response.data);});
}[{id: 34, name: Bag, slug: bag, parent: 0, description: ...

then 的方式异步回调

在 Dart 中,then 方法用于处理返回了 Future 的异步操作。当 Future 完成时,then 方法所传入的回调函数会被执行

2.2 异步等待 await

import 'package:dio/dio.dart';void main() async {Dio dio = Dio();Response<String> response =await dio.get("https://wpapi.ducafecat.tech/products/categories");print(response.data);
}[{id: 34, name: Bag, slug: bag, parent: 0, description: ...

async 写在函数定义 await 写在异步请求头

在 Dart 中,async 和 await 关键字用于简化异步编程,使得代码逻辑和控制流更像是同步代码。 它们主要用于处理 Future 对象,从而让异步代码更加易读

  1. async 关键字
    • 当你在函数声明时使用 async 关键字时,表示这个函数是异步函数
    • async 函数总是返回一个 Future,即使你直接返回一个非 Future 类型的值(这种情况下这个值将会被自动包装成一个 Future
  2. await 关键字
    • await 关键字只能在 async 函数中使用,它用于等待一个返回 Future 的表达式完成,并获取其结果
    • 在 await 关键字之后的代码会暂停执行,直到 Future 完成,并将其结果赋值给左侧的变量
   Response<String> response =await dio.get("https://wpapi.ducafecat.tech/products/categories");

在这里,await 暂停了 main 函数的执行,直到 dio.get 异步操作完成,并将请求成功返回的响应赋值给 response 变量

2.3 异步返回值

import 'package:dio/dio.dart';Future<String?> getUrl(String url) async {Dio dio = Dio();Response<String> response = await dio.get(url);return response.data;
}void main() async {var content =await getUrl('https://wpapi.ducafecat.tech/products/categories');print(content);
}[{id: 34, name: Bag, slug: bag, parent: 0, description: ...

定义 Future<T> 返回对象

代码展示了如何使用 Dart 中的 async 和 await 关键字来处理异步 HTTP 请求,并把请求操作提取到一个单独的函数里。这种方式不仅使代码更具有模块化,还能提高可读性和维护性

3. 生成器 generate (了解)

3.1 同步生成器 sync*

Iterable<int> naturalsTo(int n) sync* {print('start');int k = 0;while (k < n) {yield k++;}print('end');
}main(List<String> args) {var it = naturalsTo(5).iterator;while (it.moveNext()) {print(it.current);}
}start
0
1
2
3
4
end

yield 会等待 moveNext 指令

使用 sync* 的场景

延迟计算: 生成器可以在需要时生成元素,而不是一次性生成所有元素

内存效率: 适用于处理大量或无限数据流,因为它们逐个生成元素,而不需要一次性加载到内存中

流控制: 可以在生成元素之间执行其他逻辑,如打印日志、计算等

总结

sync* 关键字用于定义一个同步生成器函数,yield 则用于逐个生成元素。生成器函数非常适合处理需要延迟计算、大量数据或无限数据流的场景。它们提高了内存效率,同时保持代码简洁和易读

3.2 异步生成器 async*

import 'dart:async';Stream<int> asynchronousNaturalsTo(int n) async* {print('start');int k = 0;while (k < n) {yield k++;}print('end');
}main(List<String> args) {// 流监听// asynchronousNaturalsTo(5).listen((onData) {//   print(onData);// });// 流监听 StreamSubscription 对象StreamSubscription subscription = asynchronousNaturalsTo(5).listen(null);subscription.onData((value) {print(value);// subscription.pause();});
}start
0
1
2
3
4
end

以流的方式一次性推送

StreamSubscription 对象进行流监听控制

使用 StreamSubscription 的优势

流控制StreamSubscription 对象允许你控制流的行为,比如暂停 (pause) 和恢复 (resume) 流

取消订阅: 你可以通过 subscription.cancel() 方法取消订阅流,避免资源浪费

监听错误和完成: 可以使用 subscription.onError 和 subscription.onDone 方法分别处理错误和流完成事件

3.3 递归生成器 sync*

Iterable<int> naturalsDownFrom(int n) sync* {if (n > 0) {yield n;yield* naturalsDownFrom(n - 1);}
}main(List<String> args) {var it = naturalsDownFrom(5).iterator;while (it.moveNext()) {print(it.current);}
}5
4
3
2
1

yield* 以指针的方式传递递归对象,而不是整个同步对象

4. 类型定义 typedef

4.1 typedef 定义使用

采用 typedef

typedef MyPrint = void Function(String val);class PrintClass {MyPrint print;PrintClass(this.print);
}main() {PrintClass coll = PrintClass((String val) => print(val));coll.print('hello world');
}hello world

未采用 typedef

class PrintClass {void Function(String val) print;PrintClass(this.print);
}main() {PrintClass coll = PrintClass((String val) => print(val));coll.print('hello world');
}hello world

4.2 简化常用类型定义

定义

typedef MapStringAny = Map<String, dynamic>;
typedef MapAnyString = Map<dynamic, String>;
typedef MapStringString = Map<String, String>;
typedef MapStringDouble = Map<String, double>;
typedef MapDoubleString = Map<double, String>;
typedef MapDoubleDouble = Map<double, double>;
typedef MapIntInt = Map<int, int>;
typedef MapIntDouble = Map<int, double>;typedef ListString = List<String>;
typedef ListInt = List<int>;
typedef ListDouble = List<double>;
typedef ListAny = List<dynamic>;

使用

main() {ListString p = [];p.add('a');p.add('b');p.add('c');MapStringAny m = {};m['a'] = 1;m['b'] = 2;m['c'] = 3;
}

5. 空安全

5.1 默认不可空

String title = 'ducafecat';

5.2 type? 可空

String? title = null;

5.3 value! 值保证不为空,主观上

String? title = 'ducafecat';
String newTitle = title!;

就是骗一骗编译器

5.4 value?. 不为空才执行

String? title = 'ducafecat';
bool isEmpty = title?.isEmpty();

5.5 value?? 如果空执行

String? title = 'ducafecat';
String newTitle = title ?? 'cat';

像构里面就挺好用的

5.6 late 声明

延迟加载修饰符

声明一个不可空的变量,并在声明后初始化

late String description;void main() {description = 'Feijoada!';print(description);
}

本来要在声明的时候初始化的,加上 late 就告诉编译器我们后面再初始化

5.7 late 类成员延迟初始

class WPHttpService extends GetxService {late final Dio _dio;@overridevoid onInit() {..._dio = Dio(options);...}

加上 late 后就可以不用构造函数的时候初始化了

5.8 List、泛型

  List<String?>? l;l = [];l.add(null);l.add('a');print(l);

5.9 Map

  Map<String, String?>? m;m = {};m['a'] = 'b';m['b'] = null;print(m);

* 可能返回空

6. 扩展 extension

extension 本质上还是和继承一样扩展了方法

但这是一种简洁优雅的方式,你可以想想之前继承的繁琐

6.1 示例 扩展日期时间

加入依赖包 pubspec.yaml

dependencies:intl: ^0.17.0

编写扩展类 ExDateTime

import 'package:intl/intl.dart';extension ExDateTime on DateTime {/// 方法,格式化日期 yyyy-MM-ddString toDateString({String format = 'yyyy-MM-dd'}) =>DateFormat(format).format(this);// 属性int get nowTicket => this.microsecondsSinceEpoch;
}main() {var now = DateTime.now();print(now.toDateString());print(now.nowTicket);
}

我们给可以扩展类加个前缀 Ex 这样一看就知道是扩展

6.2 业务场景

功能函数

视图组件

创作不易,希望读者三连支持 💖
赠人玫瑰,手有余香 💖

这篇关于Flutter基础 -- Dart 语言 -- 进阶使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1027005

相关文章

Nginx中配置使用非默认80端口进行服务的完整指南

《Nginx中配置使用非默认80端口进行服务的完整指南》在实际生产环境中,我们经常需要将Nginx配置在其他端口上运行,本文将详细介绍如何在Nginx中配置使用非默认端口进行服务,希望对大家有所帮助... 目录一、为什么需要使用非默认端口二、配置Nginx使用非默认端口的基本方法2.1 修改listen指令

从基础到进阶详解Python条件判断的实用指南

《从基础到进阶详解Python条件判断的实用指南》本文将通过15个实战案例,带你大家掌握条件判断的核心技巧,并从基础语法到高级应用一网打尽,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录​引言:条件判断为何如此重要一、基础语法:三行代码构建决策系统二、多条件分支:elif的魔法三、

Python WebSockets 库从基础到实战使用举例

《PythonWebSockets库从基础到实战使用举例》WebSocket是一种全双工、持久化的网络通信协议,适用于需要低延迟的应用,如实时聊天、股票行情推送、在线协作、多人游戏等,本文给大家介... 目录1. 引言2. 为什么使用 WebSocket?3. 安装 WebSockets 库4. 使用 We

python中的显式声明类型参数使用方式

《python中的显式声明类型参数使用方式》文章探讨了Python3.10+版本中类型注解的使用,指出FastAPI官方示例强调显式声明参数类型,通过|操作符替代Union/Optional,可提升代... 目录背景python函数显式声明的类型汇总基本类型集合类型Optional and Union(py

Java使用正则提取字符串中的内容的详细步骤

《Java使用正则提取字符串中的内容的详细步骤》:本文主要介绍Java中使用正则表达式提取字符串内容的方法,通过Pattern和Matcher类实现,涵盖编译正则、查找匹配、分组捕获、数字与邮箱提... 目录1. 基础流程2. 关键方法说明3. 常见场景示例场景1:提取所有数字场景2:提取邮箱地址4. 高级

使用SpringBoot+InfluxDB实现高效数据存储与查询

《使用SpringBoot+InfluxDB实现高效数据存储与查询》InfluxDB是一个开源的时间序列数据库,特别适合处理带有时间戳的监控数据、指标数据等,下面详细介绍如何在SpringBoot项目... 目录1、项目介绍2、 InfluxDB 介绍3、Spring Boot 配置 InfluxDB4、I

使用Java读取本地文件并转换为MultipartFile对象的方法

《使用Java读取本地文件并转换为MultipartFile对象的方法》在许多JavaWeb应用中,我们经常会遇到将本地文件上传至服务器或其他系统的需求,在这种场景下,MultipartFile对象非... 目录1. 基本需求2. 自定义 MultipartFile 类3. 实现代码4. 代码解析5. 自定

使用Python实现无损放大图片功能

《使用Python实现无损放大图片功能》本文介绍了如何使用Python的Pillow库进行无损图片放大,区分了JPEG和PNG格式在放大过程中的特点,并给出了示例代码,JPEG格式可能受压缩影响,需先... 目录一、什么是无损放大?二、实现方法步骤1:读取图片步骤2:无损放大图片步骤3:保存图片三、示php

使用Python实现一个简易计算器的新手指南

《使用Python实现一个简易计算器的新手指南》计算器是编程入门的经典项目,它涵盖了变量、输入输出、条件判断等核心编程概念,通过这个小项目,可以快速掌握Python的基础语法,并为后续更复杂的项目打下... 目录准备工作基础概念解析分步实现计算器第一步:获取用户输入第二步:实现基本运算第三步:显示计算结果进

Python进阶之列表推导式的10个核心技巧

《Python进阶之列表推导式的10个核心技巧》在Python编程中,列表推导式(ListComprehension)是提升代码效率的瑞士军刀,本文将通过真实场景案例,揭示列表推导式的进阶用法,希望对... 目录一、基础语法重构:理解推导式的底层逻辑二、嵌套循环:破解多维数据处理难题三、条件表达式:实现分支