- 什么是Islote
- 使用 Islote 處理網(wǎng)絡請求的數(shù)據(jù)
- http 請求數(shù)據(jù)
- 使用 compute 在后臺處理數(shù)據(jù)
- 異步渲染數(shù)據(jù)
- PhotoListView UI Widget
3.效果
4.完整代碼
什么是Islote
Dart 應用一般都是單線程運行的,這就可能導致一些隱藏問題,比如當你的數(shù)據(jù)處理時間特別長的時候,用戶體驗上可能就會出現(xiàn)問題。
Native 本身是可以進行多線程進行一些操作,F(xiàn)lutter 中封裝了 Isolate 來進行線程調(diào)度
Isolate 在 native 開發(fā)使用的包是import '_isolates_io.dart' ,在 web 開發(fā)中使用的是 _isolates_web
并且 Isolate 提供了 computed 方法,用于將數(shù)據(jù)與 callback 結(jié)合
/// 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 方法,可以將數(shù)據(jù)拋給一個方法去處理,并且在后臺執(zhí)行:
compute(callback, data)
使用 Islote 處理網(wǎng)絡請求的數(shù)據(jù)
1、http 請求數(shù)據(jù)
這里請求了 網(wǎng)易新聞的一個 json
http.Response response = await client.get(
'https://3g.163.com/photocenter/api/list/0001/00AP0001,3R710001,4T8E0001/30/100.json');
print(response.body)
首先我們拿到了數(shù)據(jù),如果這個時候直接處理,我們可能采用的方式是:
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 在后臺處理數(shù)據(jù)
為了方便數(shù)據(jù)的處理,創(chuàng)建一個 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 用來處理單個圖片,將數(shù)據(jù)抽出來。
而 generatorPhoto 方法則是將網(wǎng)絡請求 decode 之后,在遍歷處理數(shù)據(jù)。
準備好 callback 之后,就可以將數(shù)據(jù)丟給 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 處理完的數(shù)據(jù)返回,當然 _fetchPhoto 這個方法依舊是異步的。
3、異步渲染數(shù)據(jù)
上面處理之后, _fetchPhotos 返回的仍然是異步結(jié)果,在 Widget 中不能直接在 builder 渲染組件,需要通過異步渲染。
FutureBuilder 構(gòu)造函數(shù)如下:
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 是異步處理的結(jié)果,結(jié)果可能是 null,builder 是渲染 Widget 的處理邏輯
builder 接受兩個參數(shù),除了默認的 builder 會接收的 context 上下文數(shù)據(jù)外,還接收 snapshot 參數(shù)。
其中 future 的結(jié)果都是從 snapshot 中獲取,snapshot 的類型其實是 AsyncSnapshot.
AsyncSnapshot 其實有幾種狀態(tài),分別代表數(shù)據(jù)數(shù)據(jù)的進度:
AsyncSnapshot.ConnectionState.none
AsyncSnapshot.ConnectionState.waiting
AsyncSnapshot.ConnectionState.active
AsyncSnapshot.ConnectionState.done
而 AsyncSnapshot 本身提供了 hasData 和 hasError 兩個屬性快速判斷是否有錯誤或者數(shù)據(jù),提供了 error 和 data 快速獲取數(shù)據(jù)或者錯誤信息。
因此 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 判斷是否有錯誤,如果存在錯誤,或者直接渲染錯誤頁。
如果有數(shù)據(jù),渲染真正的 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);
},
);
}
}
三、效果:

四、完整代碼
轉(zhuǎn)載自:http://www.ptbird.cn/flutter-isolate-compute-http-data.html