面试题答案
一键面试请求并发数优化
- 实现思路:
- 使用
Dart
的Isolate
或compute
函数来实现多任务并发执行。对于网络请求,Flutter
的http
库本身支持异步操作。可以利用Future.wait
结合一个List<Future>
来控制并发数量。通过创建一个固定大小的请求池,当有新请求进入队列时,如果请求池未满,则立即执行请求;如果已满,则等待池中有请求完成后再执行新请求。
- 使用
- 关键代码片段:
import 'dart:async';
import 'package:http/http.dart' as http;
// 控制并发数
const int concurrentLimit = 5;
Future<List<http.Response>> sendRequests(List<Uri> urls) async {
List<Future<http.Response>> futures = [];
List<http.Response> responses = [];
int index = 0;
while (index < urls.length) {
int endIndex = index + concurrentLimit;
if (endIndex > urls.length) {
endIndex = urls.length;
}
List<Uri> subUrls = urls.sublist(index, endIndex);
List<Future<http.Response>> subFutures = subUrls.map((url) => http.get(url)).toList();
futures.addAll(subFutures);
List<http.Response> subResponses = await Future.wait(subFutures);
responses.addAll(subResponses);
index = endIndex;
}
return responses;
}
缓存策略优化
- 实现思路:
- 可以使用内存缓存和磁盘缓存相结合的方式。在内存中,使用
Map
来存储请求的结果,每次发起请求前先检查内存缓存中是否有对应的结果。对于磁盘缓存,可以使用shared_preferences
(简单数据存储)或更复杂的数据库如sqflite
(适用于较大数据量)。设置缓存的过期时间,当缓存过期后重新发起网络请求并更新缓存。
- 可以使用内存缓存和磁盘缓存相结合的方式。在内存中,使用
- 关键代码片段:
- 内存缓存示例:
Map<String, dynamic> inMemoryCache = {};
Future<dynamic> getWithCache(Uri url) async {
if (inMemoryCache.containsKey(url.toString())) {
return inMemoryCache[url.toString()];
}
http.Response response = await http.get(url);
inMemoryCache[url.toString()] = response;
return response;
}
- 磁盘缓存示例(使用
shared_preferences
):
import 'package:shared_preferences/shared_preferences.dart';
Future<dynamic> getWithDiskCache(Uri url) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String cachedResponse = prefs.getString(url.toString());
if (cachedResponse != null) {
return cachedResponse;
}
http.Response response = await http.get(url);
prefs.setString(url.toString(), response.body);
return response;
}
网络异常处理及队列正常执行
- 实现思路:
- 对于每个网络请求,使用
try - catch
块捕获异常。当出现异常时,记录异常信息,并将请求重新加入队列等待重试。可以设置重试次数限制,达到限制次数后放弃重试并将异常信息返回给调用者。为了保证队列正常执行,可以使用Stream
和StreamController
来管理请求队列,在异常处理时,确保队列的状态能够正确更新。
- 对于每个网络请求,使用
- 关键代码片段:
import 'dart:async';
import 'package:http/http.dart' as http;
class RequestQueue {
final StreamController<Uri> _queueController = StreamController<Uri>();
final int maxRetries = 3;
RequestQueue() {
_queueController.stream.listen((Uri url) async {
int retryCount = 0;
while (retryCount < maxRetries) {
try {
http.Response response = await http.get(url);
// 处理响应
print('Request to $url successful: ${response.statusCode}');
break;
} catch (e) {
retryCount++;
print('Request to $url failed, retry $retryCount: $e');
if (retryCount == maxRetries) {
print('Max retries reached for $url, giving up.');
}
}
}
});
}
void addRequest(Uri url) {
_queueController.sink.add(url);
}
void dispose() {
_queueController.close();
}
}
// 使用示例
void main() {
RequestQueue queue = RequestQueue();
queue.addRequest(Uri.parse('https://example.com/api'));
// 用完后记得释放资源
queue.dispose();
}