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);
}
}
要更新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);
}
}
這就是典型的進行網絡或資料庫調用的方式
在Android上,當您繼承AsyncTask時,通常會覆寫3個方法,OnPreExecute、doInBackground和onPostExecute。 在Flutter中沒有這種模式的等價物,隻需等待一個長時間運作的函數,而Dart的事件循環将負責其餘的事情。
但是,有時可能需要處理大量資料,導緻UI可能會挂起。在Flutter中,可以利用多個CPU核心來執行耗時或計算密集型任務。 這是通過使用Isolates來完成的。
是一個獨立的執行線程,它運作時不會與主線程共享任何記憶體。這意味着你不能從該線程通路變量或通過調用setState來更新你的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;
}
完整示例:
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<MyAppHome> {
@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;
}
}