- 什么是Islote
- 使用 Islote 处理网络请求的数据
- http 请求数据
- 使用 compute 在后台处理数据
- 异步渲染数据
- PhotoListView UI Widget
3.效果
4.完整代码
什么是Islote
Dart 应用一般都是单线程运行的,这就可能导致一些隐藏问题,比如当你的数据处理时间特别长的时候,用户体验上可能就会出现问题。
Native 本身是可以进行多线程进行一些操作,Flutter 中封装了 Isolate 来进行线程调度
Isolate 在 native 开发使用的包是import '_isolates_io.dart' ,在 web 开发中使用的是 _isolates_web
并且 Isolate 提供了 computed 方法,用于将数据与 callback 结合
/// Spawn an isolate, run `callback` on that isolate, passing it `message`, and
/// (eventually) return the value returned by `callback`.
final _ComputeImpl compute = _isolates.compute;
也就是说通过 compute 方法,可以将数据抛给一个方法去处理,并且在后台执行:
compute(callback, data)
使用 Islote 处理网络请求的数据
1、http 请求数据
这里请求了 网易新闻的一个 json
http.Response response = await client.get(
'https://3g.163.com/photocenter/api/list/0001/00AP0001,3R710001,4T8E0001/30/100.json');
print(response.body)
首先我们拿到了数据,如果这个时候直接处理,我们可能采用的方式是:
Future<List<Photo>> _fetchPhotos(http.Client client) async {
http.Response res =
await client.get('https://3g.163.com/photocenter/api/list/0001/00AP0001,3R710001,4T8E0001/30/100.json');
List list = json.decode(res.body);
return list.map((item) {
return Photo.fromJson(item);
}).toList();
}
上面这种方式明显是阻塞的,并且如果我们要渲染占位图,就需要使用 state 控制占位图的渲染
2、使用 compute 在后台处理数据
为了方便数据的处理,创建一个 callback 方法:
class Photo {
final String thumbnailUrl;
Photo({this.thumbnailUrl});
factory Photo.fromJson(Map<String, dynamic> data) {
return Photo(
thumbnailUrl: data['tcover'] as String,
);
}
}
List<Photo> generatorPhoto(String body) {
List list = json.decode(body);
return list.map<Photo>((item) => Photo.fromJson(item)).toList();
}
上面代码中 Photo Class 用来处理单个图片,将数据抽出来。
而 generatorPhoto 方法则是将网络请求 decode 之后,在遍历处理数据。
准备好 callback 之后,就可以将数据丢给 callback
Future<List<Photo>> _fetchPhotos(http.Client client) async {
http.Response response = await client.get(
'https://3g.163.com/photocenter/api/list/0001/00AP0001,3R710001,4T8E0001/30/100.json');
return compute(generatorPhoto, response.body);
}
return compute(generatorPhoto, response.body); 会将 generatorPhoto 处理完的数据返回,当然 _fetchPhoto 这个方法依旧是异步的。
3、异步渲染数据
上面处理之后, _fetchPhotos 返回的仍然是异步结果,在 Widget 中不能直接在 builder 渲染组件,需要通过异步渲染。
FutureBuilder 构造函数如下:
const FutureBuilder({
Key key,
this.future,
this.initialData,
@required this.builder,
})
this.future 的声明如下:
/// The asynchronous computation to which this builder is currently connected,
/// possibly null.
///
/// If no future has yet completed, including in the case where [future] is
/// null, the data provided to the [builder] will be set to [initialData].
final Future<T> future;
future 是异步处理的结果,结果可能是 null,builder 是渲染 Widget 的处理逻辑
builder 接受两个参数,除了默认的 builder 会接收的 context 上下文数据外,还接收 snapshot 参数。
其中 future 的结果都是从 snapshot 中获取,snapshot 的类型其实是 AsyncSnapshot.
AsyncSnapshot 其实有几种状态,分别代表数据数据的进度:
AsyncSnapshot.ConnectionState.none
AsyncSnapshot.ConnectionState.waiting
AsyncSnapshot.ConnectionState.active
AsyncSnapshot.ConnectionState.done
而 AsyncSnapshot 本身提供了 hasData 和 hasError 两个属性快速判断是否有错误或者数据,提供了 error 和 data 快速获取数据或者错误信息。
因此 builder 中逻辑如下:
@override
Widget build(BuildContext context) {
return FutureBuilder<List<Photo>>(
future: _fetchPhotos(http.Client()),
builder: (context, snapshot) {
if (snapshot.hasError) {
print(snapshot.error);
}
if (snapshot.hasData) {
return PhotoListView(list: snapshot.data);
} else {
return Center(child: CircularProgressIndicator());
}
},
);
}
首先通过 snapshot.hasError 判断是否有错误,如果存在错误,或者直接渲染错误页。
如果有数据,渲染真正的 Widget,否则渲染一个 loading UI
4、PhotoListView UI Widget
这个比较简单,就是一个 GridView:
class PhotoListView extends StatelessWidget {
final List<Photo> list;
PhotoListView({Key key, this.list}) : super(key: key);
@override
Widget build(BuildContext context) {
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
),
itemCount: list.length,
itemBuilder: (context, i) {
return Image.network(list[i].thumbnailUrl);
},
);
}
}
三、效果:
四、完整代码
转载自:http://www.ptbird.cn/flutter-isolate-compute-http-data.html