flutter实现异步UI

网友投稿 715 2022-05-29

1.runOnUiThread 在Flutter中等价于什么

Dart是单线程执行模型,支持Isolates(在另一个线程上运行Dart代码的方式)、事件循环和异步编程。 除非您启动一个Isolate,否则您的Dart代码将在主UI线程中运行,并由事件循环驱动。可以在UI线程上运行网络请求代码而不会导致UI挂起,因为网络请求是异步的:

loadData() async { String dataURL = "https://jsonplaceholder.typicode.com/posts"; try{ Response response = await Dio().get(dataURL,options: Options(responseType: ResponseType.json),); setState(() {// 更新UI json = response.data; }); }catch(e){ print(e); } }

1

2

3

4

5

6

7

8

9

10

11

要更新UI,可以调用setState,这会触发build方法再次运行并更新数据。

2.AsyncTask和IntentService在Flutter中等价于什么

在Android中,当你想访问一个网络资源时,你通常会创建一个AsyncTask,它将在UI线程之外运行代码来防止你的UI被阻塞。 AsyncTask有一个线程池,可以为你管理线程。

由于Flutter是单线程的,运行一个事件循环(如Node.js),所以您不必担心线程管理或者使用AsyncTasks、IntentServices。

要异步运行代码,可以将函数声明为异步函数,并在该函数中等待这个耗时任务:

loadData() async { String dataURL = "https://jsonplaceholder.typicode.com/posts"; try{ Response response = await Dio().get(dataURL,options: Options(responseType: ResponseType.json),); setState(() {// 更新UI json = response.data; }); }catch(e){ print(e); } }

1

2

3

4

5

6

7

8

9

10

11

这就是典型的进行网络或数据库调用的方式

在Android上,当您继承AsyncTask时,通常会覆盖3个方法,OnPreExecute、doInBackground和onPostExecute。 在Flutter中没有这种模式的等价物,只需等待一个长时间运行的函数,而Dart的事件循环将负责其余的事情。

但是,有时可能需要处理大量数据,导致UI可能会挂起。在Flutter中,可以利用多个CPU内核来执行耗时或计算密集型任务。 这是通过使用Isolates来完成的。

是一个独立的执行线程,它运行时不会与主线程共享任何内存。这意味着你不能从该线程访问变量或通过调用setState来更新你的UI。

Isolate的例子,以及如何与主线程通信和共享数据以更新UI:

List messages; loadData() async { // 当前线程的信息的接收者 ReceivePort receivePort = new ReceivePort(); /** * 创建并生成与当前隔离共享相同代码的隔离。 * Isolate.spawn 接受的方法必须是静态的或是一个顶层函数 * 传递当前接收者receivePort.sendPort给其他线程,那么其他线程就可以通过它,与当前线程通信 * */ await Isolate.spawn(dataLoader, receivePort.sendPort); SendPort sendPort = await receivePort.first; String dataURL = "https://jsonplaceholder.typicode.com/posts"; /// 向其他线程发送消息 var msg = await sendReceive(sendPort,dataURL); setState(() { /// 更新UI,setState会触发build的执行 messages = msg; print(messages); }); } static dataLoader(SendPort sendPort) async{ /// 其他线程的消息接收者 ReceivePort receivePort = new ReceivePort(); /// 通知其他isolate,当前isolate监听的端口 sendPort.send(receivePort.sendPort); await for(var msg in receivePort){ String data = msg[0]; // 获取URL SendPort replyTo = msg[1]; // 回传消息用的 String dataURL = data; /// 进行网络请求 Response response = await Dio().get(dataURL,options: Options(responseType: ResponseType.json),); /// 将结果回传回去 replyTo.send(response.data); } } /// 向其他线程发送消息 Future sendReceive(SendPort port,msg){ /// 当前线程的接收者 ReceivePort receivePort = new ReceivePort(); /// 向其他线程发送消息 port.send([msg,receivePort.sendPort]); return receivePort.first; }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

“dataLoader”是在它自己的独立执行线程中运行的隔离区,可以在其中执行CPU密集型任务,例如解析大于1万的JSON或执行计算密集型数学计算。

完整示例:

import 'dart:convert'; import 'dart:isolate'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; void main() => runApp(DemoApp()); class DemoApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( title: '导航演示1', home: new MyAppHome(), ); } } class MyAppHome extends StatefulWidget { @override MyAppHomeState createState() => MyAppHomeState(); } class MyAppHomeState extends State { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Hello"), ), body: Center( child: RaisedButton( child: Text("Go"), onPressed: () { loadData(); }, ), ), ); } List messages; loadData() async { // 当前线程的信息的接收者 ReceivePort receivePort = new ReceivePort(); /** * 创建并生成与当前隔离共享相同代码的隔离。 * Isolate.spawn 接受的方法必须是静态的或是一个顶层函数 * 传递当前接收者receivePort.sendPort给其他线程,那么其他线程就可以通过它,与当前线程通信 * */ await Isolate.spawn(dataLoader, receivePort.sendPort); SendPort sendPort = await receivePort.first; String dataURL = "https://jsonplaceholder.typicode.com/posts"; /// 向其他线程发送消息 List msg = await sendReceive(sendPort,dataURL); setState(() { /// 更新UI,setState会触发build的执行 messages = msg; print(messages[0]["title"]); }); } static dataLoader(SendPort sendPort) async{ /// 其他线程的消息接收者 ReceivePort receivePort = new ReceivePort(); /// 通知其他isolate,当前isolate监听的端口 sendPort.send(receivePort.sendPort); await for(var msg in receivePort){ String data = msg[0]; // 获取URL SendPort replyTo = msg[1]; // 回传消息用的 String dataURL = data; /// 进行网络请求 Response response = await Dio().get(dataURL); /// 将结果回传回去 replyTo.send(jsonDecode(response.toString())); } } /// 向其他线程发送消息 Future sendReceive(SendPort port,msg){ /// 当前线程的接收者 ReceivePort receivePort = new ReceivePort(); /// 向其他线程发送消息 port.send([msg,receivePort.sendPort]); return receivePort.first; } }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

flutter实现异步UI

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

Flutter iOS 任务调度

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:《企业私有云建设指南》一第2章 企业云计算涉及的技术选型和管理
下一篇:【重构前端知识体系之HTML】2022,你还会来看HTML吗?带你重温亦或走进!
相关文章