你是怎么把工作放到后台線程的?
由於 Flutter 是單線程並且跑着一個 event loop 的(就像 Node.js 那樣),你不必為線程管理或是開啟后台線程而操心。如果你正在做 I/O 操作,如訪問磁盤或網絡請求,安全地使用 async
/ await
就完事了。如果,在另外的情況下,你需要做讓 CPU 執行繁忙的計算密集型任務,你需要使用 Isolate
來避免阻塞 event loop。
對於 I/O 操作,通過關鍵字 async
,把方法聲明為異步方法,然后通過await
關鍵字等待該異步方法執行完成(譯者語:這和javascript中是相同的):
這就是對諸如網絡請求或數據庫訪問等 I/O 操作的典型做法。
然而,有時候你需要處理大量的數據,這會導致你的 UI 掛起。在 Flutter 中,使用 Isolate
來發揮多核心 CPU 的優勢來處理那些長期運行或是計算密集型的任務。
Isolates 是分離的運行線程,並且不和主線程的內存堆共享內存。這意味着你不能訪問主線程中的變量,或者使用 setState()
來更新 UI。正如它們的名字一樣,Isolates 不能共享內存。
下面的例子展示了一個簡單的 isolate,是如何把數據返回給主線程來更新 UI 的
import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:async'; import 'dart:isolate'; void main() { runApp(SampleApp()); } class SampleApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Sample App', theme: ThemeData( primarySwatch: Colors.blue, ), home: SampleAppPage(), ); } } class SampleAppPage extends StatefulWidget { SampleAppPage({Key key}) : super(key: key); @override _SampleAppPageState createState() => _SampleAppPageState(); } class _SampleAppPageState extends State<SampleAppPage> { List widgets = []; @override void initState() { super.initState(); loadData(); } showLoadingDialog() { if (widgets.length == 0) { return true; } return false; } getBody() { if (showLoadingDialog()) { return getProgressDialog(); } else { return getListView(); } } getProgressDialog() { return Center(child: CircularProgressIndicator()); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Sample App"), ), body: getBody()); } ListView getListView() => ListView.builder( itemCount: widgets.length, itemBuilder: (BuildContext context, int position) { return getRow(position); }); Widget getRow(int i) { return Padding(padding: EdgeInsets.all(10.0), child: Text("Row ${widgets[i]["title"]}")); } loadData() async { ReceivePort receivePort = ReceivePort(); await Isolate.spawn(dataLoader, receivePort.sendPort); // The 'echo' isolate sends its SendPort as the first message SendPort sendPort = await receivePort.first; List msg = await sendReceive(sendPort, "https://jsonplaceholder.typicode.com/posts"); setState(() { widgets = msg; }); } // the entry point for the isolate static dataLoader(SendPort sendPort) async { // Open the ReceivePort for incoming messages. ReceivePort port = ReceivePort(); // Notify any other isolates what port this isolate listens to. sendPort.send(port.sendPort); await for (var msg in port) { String data = msg[0]; SendPort replyTo = msg[1]; String dataURL = data; http.Response response = await http.get(dataURL); // Lots of JSON to parse replyTo.send(json.decode(response.body)); } } Future sendReceive(SendPort port, msg) { ReceivePort response = ReceivePort(); port.send([msg, response.sendPort]); return response.first; } }
遇到問題看上一篇:
這里還是補充一下
首先在pubspec.yaml中添加https://www.cnblogs.com/wf-l5201314/p/10315922.html