面试题答案
一键面试处理高并发网络请求
- 原理:
- 使用Dio的
Future.wait
方法来并发执行多个网络请求。Dio是一个强大的HTTP客户端库,Future.wait
可以将多个Future
对象组成一个列表,当列表中的所有Future
都完成时,返回一个包含所有结果的新Future
。 - 控制并发请求数量,避免过多请求占用过多资源,导致性能问题或请求失败。可以使用
Stream
和StreamController
来管理请求队列,按照一定的并发数依次执行请求。
- 使用Dio的
- 代码实现:
import 'package:dio/dio.dart';
void main() async {
Dio dio = Dio();
List<Future<Response>> futures = [
dio.get('https://example.com/api1'),
dio.get('https://example.com/api2'),
dio.get('https://example.com/api3')
];
List<Response> responses = await Future.wait(futures);
responses.forEach((response) {
print(response.data);
});
}
控制并发数的示例:
import 'package:dio/dio.dart';
import 'dart:async';
void main() async {
Dio dio = Dio();
List<String> urls = [
'https://example.com/api1',
'https://example.com/api2',
'https://example.com/api3',
'https://example.com/api4'
];
int concurrency = 2;
StreamController<List<Response>> controller = StreamController<List<Response>>();
Stream<List<Response>> stream = controller.stream;
List<Future<Response>> currentRequests = [];
int index = 0;
void _executeRequests() {
while (currentRequests.length < concurrency && index < urls.length) {
currentRequests.add(dio.get(urls[index]));
index++;
}
Future.wait(currentRequests).then((responses) {
controller.add(responses);
currentRequests = [];
if (index < urls.length) {
_executeRequests();
} else {
controller.close();
}
});
}
_executeRequests();
stream.listen((responses) {
responses.forEach((response) {
print(response.data);
});
});
}
动态证书验证
- 原理:
- 在Flutter中,使用Dio进行网络请求时,可以通过自定义
HttpClientAdapter
来实现动态证书验证。Dio底层依赖HttpClient
,通过创建自定义的HttpClientAdapter
,我们可以在HttpClient
建立连接时,对服务器证书进行验证。 - 可以从本地存储或远程服务器获取证书信息,在验证时与服务器提供的证书进行对比。
- 在Flutter中,使用Dio进行网络请求时,可以通过自定义
- 代码实现:
import 'package:dio/dio.dart';
import 'package:http/http.dart' as http;
import 'dart:io';
class CustomHttpClientAdapter extends HttpClientAdapter {
final String certificatePath;
CustomHttpClientAdapter(this.certificatePath);
@override
Future<http.StreamedResponse> send(BaseOptions options, RequestOptions requestOptions) {
return createHttpClient(requestOptions).then((client) {
client.badCertificateCallback = (X509Certificate cert, String host, int port) {
// 从本地文件读取证书
SecurityContext context = SecurityContext.defaultContext;
context.setTrustedCertificates(certificatePath);
return context.verifyCertificateChain(cert, host, port);
};
return client.send(requestOptions.toHttpClientRequest());
});
}
}
void main() async {
Dio dio = Dio();
dio.httpClientAdapter = CustomHttpClientAdapter('path/to/your/certificate.pem');
try {
Response response = await dio.get('https://example.com');
print(response.data);
} catch (e) {
print(e);
}
}
自定义缓存策略
- 原理:
- 可以利用Dio的拦截器机制,在请求发出前和响应返回后进行处理。在请求发出前,检查缓存中是否有对应的请求结果,如果有且缓存未过期,则直接返回缓存数据。在响应返回后,根据自定义的缓存策略,将响应数据存入缓存,并记录缓存的过期时间。
- 可以使用
SharedPreferences
或文件系统来存储缓存数据。
- 代码实现:
import 'package:dio/dio.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';
class CustomCacheInterceptor extends Interceptor {
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String cacheKey = options.uri.toString();
String cachedData = prefs.getString(cacheKey);
if (cachedData != null) {
// 假设缓存数据格式为 {data: '...', timestamp: '...'}
Map<String, dynamic> cacheMap = json.decode(cachedData);
int currentTime = DateTime.now().millisecondsSinceEpoch;
// 假设缓存有效期为1小时(3600000毫秒)
if (currentTime - cacheMap['timestamp'] < 3600000) {
handler.resolve(Response(
requestOptions: options,
data: cacheMap['data'],
statusCode: 200,
));
return;
}
}
handler.next(options);
}
@override
void onResponse(Response response, ResponseInterceptorHandler handler) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String cacheKey = response.requestOptions.uri.toString();
int currentTime = DateTime.now().millisecondsSinceEpoch;
Map<String, dynamic> cacheMap = {
'data': response.data,
'timestamp': currentTime
};
prefs.setString(cacheKey, json.encode(cacheMap));
handler.next(response);
}
}
void main() async {
Dio dio = Dio();
dio.interceptors.add(CustomCacheInterceptor());
try {
Response response = await dio.get('https://example.com');
print(response.data);
} catch (e) {
print(e);
}
}