Dart & Flutter 開發技巧 8-14
861
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
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
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小時內刪除侵權內容。