当我在flutter中运行此方法时,例如当我在手势检测器中的onTap
flutter冻结2次时,当get
方法调用时(我认为这是因为Dio-json转换器,可能是idk(,以及当base64Decode
方法调用时
在flutter web上,当get
方法调用时,flutter完全卷曲(onSendProgress
此时也不起作用(,并且在chrome应用程序崩溃后,代码为5,可能在一两分钟后-_-
context
不是BuildContext
httpClient
是Dio HTTP客户端
transformOf
检查请求结果是否为错误,如果是,将请求结果转换为我的flutter自定义异常,抛出后返回请求结果。
请求结果大小20-50mb
Future<Uint8List> readBookFile(Identificator groupId, Identificator bookId) async {
final result = await context.httpClient.get(
'/book/file',
queryParameters: {
'groupId': groupId.toString(),
'bookId': bookId.toString(),
},
).transformOf(context);
return base64Decode(result['bookBytes']);
}
如何优化此代码以进行处置冻结?
问题
在您的情况下,base64Decode(result['bookBytes']);
是一个非常昂贵的计算。(因为它解码大数据集(20-50mb((
解决方案
您可以通过使用单独的隔离来运行上述昂贵的任务来解决此问题。(参见以下代码(
创建一个名为
parseBookBytes()
的方法,将昂贵的baseDecode64()
任务放入其中使用compute((函数在单独的隔离中执行
parseBookBytes()
。
// A function that converts a result into a Uint8List.
Uint8List parseBookBytes(var bookBytes) {
return base64Decode(bookBytes);
}
Future<Uint8List> readBookFile(Identificator groupId, Identificator bookId) async {
final result = await context.httpClient.get(
'/book/file',
queryParameters: {
'groupId': groupId.toString(),
'bookId': bookId.toString(),
},
).transformOf(context);
return compute(parseBookBytes, result['bookBytes']); //run on a separate isolate using compute() function
}
资源
- 链接1
- 链接2
- 链接3
为了解决这个问题,我创建了2个解析和2个计算函数
Uint8List parseBase64(String base64) {
return base64Decode(base64);
}
Future<Uint8List> parseBase64Compute(String base64) {
return compute<String, Uint8List>(parseBase64, base64.trim());
}
Map<String, dynamic> parseJson(String json) {
return jsonDecode(json);
}
Future<Map<String, dynamic>> parseJsonCompute(String base64) {
return compute<String, Map<String, dynamic>>(parseJson, base64);
}
在我为json 创建了简单的dio转换器之后
class JsonTransformer extends DefaultTransformer {
JsonTransformer() : super(jsonDecodeCallback: parseJsonCompute);
}
并应用此
httpClient.transformer = JsonTransformer();
重构后的函数是
Future<Uint8List> readBookFile(Identificator groupId, Identificator bookId) async {
final result = await context.httpClient.get(
'/book/file',
queryParameters: {
'groupId': groupId.toString(),
'bookId': bookId.toString(),
},
).transformOf(context);
return parseBase64Compute(result['bookBytes']);;
}