面试题答案
一键面试架构设计
- 分层架构
- 数据层:负责与网络进行交互,封装http请求细节。在此层创建
HttpService
类,使用http
或dio
插件处理具体的HTTP请求。例如:
- 数据层:负责与网络进行交互,封装http请求细节。在此层创建
class HttpService {
final Dio _dio = Dio();
Future<Response> uploadFile(String url, FormData formData) async {
return _dio.post(url, data: formData);
}
Future<Response> downloadFile(String url, String savePath) async {
return _dio.download(url, savePath);
}
}
- **业务逻辑层**:根据不同用户角色调整请求参数。创建`RequestBuilder`类,负责构建请求。例如:
class RequestBuilder {
static Map<String, dynamic> buildParams(UserRole role) {
if (role == UserRole.admin) {
return {'role': 'admin', 'extra_param': 'admin_only'};
} else {
return {'role': 'user'};
}
}
}
- **表现层**:调用业务逻辑层和数据层方法发起请求。在页面或视图模型中调用上述方法。
2. 依赖注入
使用provider
或get_it
等依赖注入库,将HttpService
等实例注入到需要的地方,提高代码的可测试性和可维护性。例如,使用get_it
:
final getIt = GetIt.instance;
getIt.registerSingleton<HttpService>(HttpService());
在需要使用的地方:
final httpService = getIt<HttpService>();
性能优化
- 缓存策略
对于一些不经常变化的数据请求,设置缓存机制。可以使用
dio
的CacheManager
。例如:
var cacheManager = CacheManager(
Config(
'my_cache_key',
maxStale: const Duration(days: 7),
),
);
_dio.interceptors.add(cacheManager.interceptor);
- 并发请求管理
对于多个网络请求,可以使用
Future.wait
进行并发处理,但要注意资源消耗。例如:
List<Future<Response>> requests = [
httpService.fetchData1(),
httpService.fetchData2()
];
List<Response> responses = await Future.wait(requests);
- 优化网络请求
- 压缩请求和响应数据,在
dio
中可以通过设置options
启用gzip压缩:
- 压缩请求和响应数据,在
_dio.options = BaseOptions(
headers: {'Accept-Encoding': 'gzip'},
);
- 合理设置请求超时时间,避免长时间等待:
_dio.options.connectTimeout = 5000; // 5 seconds
_dio.options.receiveTimeout = 3000; // 3 seconds
代码结构组织
- 模块化
将不同类型的网络请求封装到不同的文件中。例如,
file_requests.dart
处理文件上传下载,websocket_requests.dart
处理WebSocket相关请求。 - 错误处理
在
HttpService
中统一处理网络错误。例如:
Future<Response> sendRequest(RequestOptions options) async {
try {
return await _dio.request(options);
} on DioError catch (e) {
if (e.response != null) {
// 处理HTTP错误
print('HTTP error: ${e.response.statusCode}');
} else {
// 处理其他错误,如连接超时
print('Error: ${e.message}');
}
throw e;
}
}
- 日志记录
添加日志记录功能,方便调试和排查问题。可以使用
logger
库:
import 'package:logger/logger.dart';
final logger = Logger();
Future<Response> sendRequest(RequestOptions options) async {
logger.i('Sending request to ${options.path}');
try {
return await _dio.request(options);
} catch (e) {
logger.e('Request failed: $e');
throw e;
}
}