Appearance
Flutter适时取消请求 提升应用性能 避免阻塞
应用实际运行中,不能保证请求在生命周期内100%得到执行。 一个继续中的请求,应该在用户关闭路由(组件)的过程中,被及时中断。或者在用户尝试重新发起请求前,废除现有的请求。
还有一种情况,便是前序的请求发生错误,那么要使得后续有前序依赖的请求,及时发生短路销毁。不必要的请求及时取消,无论是对客户端还是服务端都是有意义的 在业务中还能保证业务安全。
Flutter取消请求的实现方式Dio为例
如果你使用Dio或者类似的请求类,(任何现代的请求类都会支持的)你无需过度封装,仅调用自带的CancelToken即可轻松实现。
dart
/// Dio核心请求实现是这样的,注意看到CancelToken,虽然可以传入null,但你别这么懒
Future<Response<T>> request<T>(
String path, {
Object? data,
Map<String, dynamic>? queryParameters,
CancelToken? cancelToken,
Options? options,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
});
/// 实际发起请求时
final CancelToken cancelToken = CancelToken();
final response = await dio.request(
'/test',
data: {'id': 12, 'name': 'dio'},
options: Options(method: 'GET'),
cancelToken: cancelToken
);
上述的请求中,我们传入了cancelToken,他可以用来控制这个请求。在一个StatefulWidget中,我们可以在dispose中调用cancelToken.cancel()来取消请求。
dart
@override
void dispose() {
cancelToken.cancel();
super.dispose();
}
这样一来页面销毁时,我们便取消了请求,异步请求将不会因为组件的销毁,而持续运行。
请求队列
既然有了CancelToken,那么我们可以考虑将请求封装到一个队列中,当队列中的请求被取消时,我们便取消队列中的所有请求。所以我们手动实现一个CancelToken Group工具类,将所有队列请求托管与此,当前序请求发生错误时,批量执行cancelToken.cancel()
即可轻而易举的完成。
dart
import 'package:dio/dio.dart';
class DioCancelTokenGroup {
final List<DioCancelToken> _cancelTokens = [];
void add(DioCancelToken cancelToken) {
_cancelTokens.add(cancelToken);
}
void remove(DioCancelToken cancelToken) {
_cancelTokens.remove(cancelToken);
}
void cancelAll(String reason) {
for (final cancelToken in _cancelTokens) {
cancelToken.cancel(reason);
}
_cancelTokens.clear();
}
}