面试题答案
一键面试性能优化方面
- 请求队列与限流:
- 创建请求队列,避免瞬间发起过多请求导致网络拥塞。
- 使用限流算法(如令牌桶算法),控制单位时间内允许发起的请求数量。
- 缓存策略:
- 对于不经常变化的数据,设置本地缓存。在发起请求前先检查缓存,若有则直接使用缓存数据,减少不必要的网络请求。
- 可以使用
shared_preferences
等本地存储方式进行简单数据缓存,对于复杂数据结构可采用数据库(如sqflite
)进行缓存。
- 并发数量控制:
- 根据设备性能和网络状况,合理设置最大并发请求数。例如,在移动端可设置并发请求数为5 - 10个,避免过多并发请求耗尽系统资源。
资源管理避免内存泄漏和应用卡顿
- 取消请求:
- 为每个请求创建
CancelToken
,在不需要该请求(如页面销毁)时,及时取消请求,避免请求完成后处理数据导致内存泄漏。
- 为每个请求创建
- 内存管理:
- 及时释放不再使用的对象,特别是在请求完成后,释放与请求相关的临时对象,如请求的参数、响应数据的临时存储对象等。
- 使用
Stream
来处理响应数据,避免一次性加载大量数据到内存中。通过Stream
可以逐块处理数据,减少内存压力。
架构设计思路
- 分层架构:
- 数据层:负责处理网络请求,封装网络请求逻辑,将请求结果返回给业务层。可以使用
Dio
等网络请求库。 - 业务层:处理业务逻辑,调用数据层的接口获取数据,并进行数据的加工和处理,将处理后的数据传递给视图层。
- 视图层:展示数据,根据业务层传递的数据进行UI渲染。
- 数据层:负责处理网络请求,封装网络请求逻辑,将请求结果返回给业务层。可以使用
- 状态管理:
- 采用
Provider
或Bloc
等状态管理模式,管理应用的状态,使视图层能够根据状态变化进行更新,同时避免视图层之间的状态传递混乱。
- 采用
关键代码片段
- 使用Dio进行网络请求(数据层示例):
import 'package:dio/dio.dart';
class ApiService {
final Dio _dio = Dio();
Future<Response> fetchData(String url) async {
try {
return await _dio.get(url);
} catch (e) {
print('Error fetching data: $e');
rethrow;
}
}
}
- 业务层调用数据层接口并处理数据示例:
class DataBloc {
final ApiService _apiService = ApiService();
Future<List<dynamic>> fetchAllData() async {
List<dynamic> allData = [];
List<String> urls = [/* 100个以上的URL列表 */];
final semaphore = Semaphore(5); // 设置最大并发数为5
for (String url in urls) {
await semaphore.acquire();
_apiService.fetchData(url).then((response) {
allData.add(response.data);
semaphore.release();
}).catchError((e) {
semaphore.release();
print('Error in request: $e');
});
}
return allData;
}
}
- 视图层使用状态管理展示数据示例(以Provider为例):
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final dataBloc = Provider.of<DataBloc>(context);
return Scaffold(
appBar: AppBar(
title: Text('Concurrent Requests'),
),
body: FutureBuilder<List<dynamic>>(
future: dataBloc.fetchAllData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(child: CircularProgressIndicator());
} else if (snapshot.hasError) {
return Center(child: Text('Error: ${snapshot.error}'));
} else {
return ListView.builder(
itemCount: snapshot.data?.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(snapshot.data![index].toString()),
);
},
);
}
},
),
);
}
}
Semaphore类定义:
class Semaphore {
int _available;
Semaphore(this._available);
Future<void> acquire() async {
while (_available <= 0) {
await Future.delayed(Duration(milliseconds: 100));
}
_available--;
}
void release() {
_available++;
}
}