isolate
由于Flutter 是单线程并且跑着一个event loop,如果在执行I/O 操作或者磁盘访问或者网络请求,可以安全的使用async / await来完成。如果让CPU 执行繁忙的计算密集型任务,导致UI的挂起,使用isolate 来进行避免阻塞event loop。
isolate 是分离的运行线程,不和主线程的内存堆共享内存。这意味着你不能访问主线程中的变量,或者使用isolate 来更新UI。
那么 ,Isolate 是如何把数据返回给主线程来更新UI的
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'dart:convert';
import 'dart:isolate';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
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 =[];
loadData()async{
// 打开ReceivePort 用来接收传入的信息
ReceivePort port = ReceivePort();
// 创建并且生成 与当前Isolate 共享相同代码的Isolate
await Isolate.spawn(dataLoader, port.sendPort);
// 流的第一个元素
SendPort sp = await port.first;
// 流的第一个元素被接手之后会关闭监听,所以再次打开一个receive port 来接收传入的信息
ReceivePort response = ReceivePort();
// 通过此发送端口向其对应的ReceivePort 发送异步信息 这个消息指的是发的参数
sp.send(
["https://www.apiopen.top/journalismApi",response.sendPort]);
// 获取端口发送来的数据
var msg = await response.first;
print(msg);
setState(() {
widgets = msg["data"]["auto"];
print(widgets.length);
});
}
// 耗时的操作放在这个方法里
// 这是Isolate 的入口函数 该函数会在新的Isolate 中进行调用,这是Isolate 的Spawn的message参数会作为调用它时的唯一参数
static dataLoader(SendPort sendPort) async{
// 打开ReceivePort 用来接收传入的信息
ReceivePort port = ReceivePort();
sendPort.send(port.sendPort);
await for (var msg in port) {
String url = msg[0];
SendPort replyTo = msg[1];
// 请求并且解析数据
var responseBody;
var http = new HttpClient();
var request = await http.getUrl(Uri.parse(url));
var response = await request.close();
if (response.statusCode == 200){
responseBody = await response.transform(utf8.decoder).join();
responseBody = json.decode(responseBody);
replyTo.send(responseBody);
}else{
print("error happend");
}
}
}
// 初始化状态的时候加载数据
@override
void initState() {
super.initState();
loadData();
}
Widget getRow (int idx){
return Padding(
padding: EdgeInsets.all(10),
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[Text("${widgets[idx]["title"]}",
style: new TextStyle(fontSize: 22,color: Colors.green),),Divider(height: 0.5,indent:0.0,color: Colors.black,)],
)
);
}
@override
Widget build(BuildContext context){
return Scaffold(
appBar: AppBar(title: new Text("Hello World")),
body: ListView.builder(
itemCount: widgets.length,
itemBuilder: (BuildContext context,int idx){
return getRow(idx);
},
),
);
}
}