Flutter网络
1、获取测试数据
2、集成网络请求工具
- Dart库
pubspec.yaml
文件,cupertino_icons:
中贴入库名与版本号,Pub get
即可
3、模型转换
3.1、Map转Json
json.encode(value);
3.2、Json转Map
json.decode(value);
3.3、创建特定模型(传参,返回特定值)
4、异步
- 多线程是包含A、B、C多个进程,异步是A进程下a、b、c任务
- 定义的方法后加
async
,耗时操作前加await
表示等待耗时操作结束后再进行下一步。 Dart规定async标记的异步函数,只能由await来调用
,不加await则按同步函数顺序执行- 常见异步操作:
- 通过网络获取数据。
- 写入数据库。
- 从文件读取数据。
4.1、Future
-
未来获取数据,内部已经被包装成异步的,单独使用时加不加async没影响
-
await
:设置等待Future包装的任务完成后,再执行下边代码,与async
搭配使用- 后边任务必须是异步才能用
await
修饰 - 当前函数也必须是异步函数
- 会阻塞后边所有代码执行,如果该函数中还有要先执行的其他代码则可不用await,而改用
.then(value) => 待耗时操作结束后执行的代码
- 后边任务必须是异步才能用
-
.then(value)
中的value为Future内最终return的值,但如果有异常,那么.then()不执行
4.1.1、.then(类型 value) {代码}.catchError((errorMessage){代码}).whenComplete((){代码}).timeout(Duration(seconds: 1));
-
不初始化直接链式调用
-
初始化后对实例链式调用
-
一个任务一个任务的执行
-
多个Future都完成后再执行
-
,onError:(){}
与.catchError()
区别:- .catchError回调只处理原始Future抛出的错误,不能处理回调函数抛出的错误
- onError只能处理当前Future的错误
- onError(){} 一次就结束,.catchError() 是链式,可多次使用
4.1.2、Future.value()
- 创建一个返回
指定value
值的Future:void testFuture() async { var future = await Future.value(1); print("future value: $future."); } testFuture(); 打印结果: 1
4.1.3、Future.delayed()
- 创建一个延迟执行的Future:
void testFuture() async { Future.delayed(Duration(seconds: 2), () { print("delayed 2秒."); }); } testFuture(); 打印结果: (2秒后打印)delayed 2秒
4.1.4、Future.timeout()
- 设置超时时限,本来Future会在2s后完成,但是
timeout
声明的是1s后超时,所以1s后Future会抛出TimeoutException
:void testFuture() async { new Future.delayed(new Duration(seconds: 2), () { return 1; }).timeout(new Duration(seconds:1)).then(print).catchError(print); } testFuture(); 打印结果: TimeoutException after 0:00:01.000000: Future not completed
4.1.5、Future.forEach()
- 根据某个集合对象,创建一系列的Future。并且会按顺序执行这些Future
void testFuture() async { Future.forEach({1,2,3}, (num){ return Future.delayed(Duration(seconds: num),(){ print("$num"); }); }); } testFuture(); 打印结果: (在1秒后)1 (再2秒后)2 (再3秒后)3,总时间为6秒
4.1.6、Future.any()
- 返回第一个执行完的Future结果,不管这个结果是正确的还是
error
:void testFuture() async { Future.any([1, 2, 5].map((delay) => new Future.delayed(new Duration(seconds: delay), () => delay))) .then(print) .catchError(print); } testFuture(); 打印结果: 1
4.1.7、Future.doWhile()
- 重复执行某个动作,
直到返回false或者Future
才退出循环,适用于一些递归操作场景:void testFuture() async { var random = new Random(); var totalDelay = 0; Future.doWhile(() { if (totalDelay > 10) { print('total delay: $totalDelay秒'); return false; } var delay = random.nextInt(5) + 1; totalDelay += delay; return new Future.delayed(new Duration(seconds: delay), () { print('等 $delay 秒'); return true; }); }).then(print).catchError(print); } testFuture(); 打印结果: 等 5 秒 等 5 秒 等 3 秒 total delay: 11 秒 null 等 4 秒 等 3 秒 total delay: 12 秒 null
4.1.8、Future.sync()
- 会同步执行其入参函数,然后调度到
microtask queue
来完成自己。也就是一个阻塞任务,会阻塞当前代码,sync
的任务执行完了,代码才能走到下一行:void testFuture() async { Future((){ print("1"); }); Future.sync(() { print("sync microtask 2"); //return Future(() {print("2"); }); Future((){ print("3"); }); Future.microtask((){ print("microtask"); }); } testFuture(); print("主队列"); 结果: sync microtask 2 主队列 microtask 1 3
- 但如果上边sync()中改成return一个Future:则sync变成普通Future,打印顺序1、2、3
4.1.9、Future.microtask
- 创建一个在
microtask queue
运行的Future。我们知道microtask queue的优先级是比event queue
高的。而一般Future是在event queue执行的。所以Future.microtask
创建的Future会优先于其他Future执行:void testFuture() async { Future((){ print("1"); }); Future((){ print("2"); }); Future.microtask((){ print("microtask"); }); } testFuture(); 打印结果: microtask 1 2
4.1.10、Future.wait()
- 等待多个
Future
完成,并收集它们的结果,有两种情况:- 所有Future都有正常结果返回。则Future的返回结果是
所有指定Future的结果的集合
:void testFuture() async { var future1 = new Future.delayed(new Duration(seconds: 1), () => 1); var future2 = new Future.delayed(new Duration(seconds: 2), () => 2); var future3 = new Future.delayed(new Duration(seconds: 3), () => 3); Future.wait({future1,future2,future3}).then(print).catchError(print); } testFuture(); 打印结果: [1, 2, 3]
- 其中一个或者几个Future发生错误,产生了error。则Future的返回结果是第一个发生错误的Future的值:
void testFuture() async { var future1 = new Future.delayed(new Duration(seconds: 1), () => 1); var future2 = new Future.delayed(new Duration(seconds: 2), () { throw 'Future发生错误啦!'; }); var future3 = new Future.delayed(new Duration(seconds: 3), () => 3); Future.wait({future1,future2,future3}).then(print).catchError(print); } testFuture(); Future发生错误啦! 打印结果:
- 所有Future都有正常结果返回。则Future的返回结果是
4.2、FutureBuilder
- 异步渲染,最终内部要
return
一个widget - 不复杂界面使用效率高,不需要对状态、数据进行存储
4.2.1、snapshot.connectionState
- 异步渲染状态
4.2.2、snapshot.data
- 异步渲染数据
4.3、scheduleMicrotask(callback)
:微任务
- Flutter有两种队列,一个是
事件队列
,一个是微任务队列
,微任务队列优先级高于事件队列 - .then() 其实也是微任务,Future加载后就将.then()加入微任务队列,所以优先级很高
注:
sleep()
会阻塞主线程
5、多线程
5.1、特点与对比异步
- 异步是单线程的,Flutter多线程更类似于多进程,因为
各线程有独立的内存空间
- 因为内存独立,所以无法直接调用修改,也没有抢占资源的问题,因此
没有锁!
5.2、修改内容
5.2.1、Isolate
:隔离
- 因为内存独立,将内部与外部隔离,因此
修改内容需要通讯
- 使用后,
端口要关闭
、线程要kill
ReceivePort()
; 创建端口Isolate.spawn(func,port)
; 创建线程,执行一个将端口作为参数的方法
port.listen((message){代码})
; 监听端口内容port.send(message)
; 发送端口内容
5.2.2、compute(func,param)
- 可以直接接收子线程的变量
- 内部是对Isolate的封装,在compute(func,param)中修改外部变量不生效
注意:Future与线程结合
- 拿到return看一下:
6、状态保持
- 混入
AutomaticKeepAliveClientMixin
类
这篇Cat的Dart异步编程对原理解析的更详细,有兴趣的可以看一下
个人总结,仅供参考
转载自:https://juejin.cn/post/7031508106739712031