MST

星途 面试题库

面试题:Flutter高并发网络请求下的性能优化与资源管理

假设在一个Flutter应用中有大量(100个以上)的网络请求需要并发处理,这些请求的数据量大小不一且响应时间不定。请详细说明你会从哪些方面进行性能优化,如何进行资源管理以避免内存泄漏和应用卡顿,并且给出一个大致的架构设计思路及关键代码片段。
21.5万 热度难度
前端开发Flutter

知识考点

AI 面试

面试题答案

一键面试

性能优化方面

  1. 请求队列与限流
    • 创建请求队列,避免瞬间发起过多请求导致网络拥塞。
    • 使用限流算法(如令牌桶算法),控制单位时间内允许发起的请求数量。
  2. 缓存策略
    • 对于不经常变化的数据,设置本地缓存。在发起请求前先检查缓存,若有则直接使用缓存数据,减少不必要的网络请求。
    • 可以使用shared_preferences等本地存储方式进行简单数据缓存,对于复杂数据结构可采用数据库(如sqflite)进行缓存。
  3. 并发数量控制
    • 根据设备性能和网络状况,合理设置最大并发请求数。例如,在移动端可设置并发请求数为5 - 10个,避免过多并发请求耗尽系统资源。

资源管理避免内存泄漏和应用卡顿

  1. 取消请求
    • 为每个请求创建CancelToken,在不需要该请求(如页面销毁)时,及时取消请求,避免请求完成后处理数据导致内存泄漏。
  2. 内存管理
    • 及时释放不再使用的对象,特别是在请求完成后,释放与请求相关的临时对象,如请求的参数、响应数据的临时存储对象等。
    • 使用Stream来处理响应数据,避免一次性加载大量数据到内存中。通过Stream可以逐块处理数据,减少内存压力。

架构设计思路

  1. 分层架构
    • 数据层:负责处理网络请求,封装网络请求逻辑,将请求结果返回给业务层。可以使用Dio等网络请求库。
    • 业务层:处理业务逻辑,调用数据层的接口获取数据,并进行数据的加工和处理,将处理后的数据传递给视图层。
    • 视图层:展示数据,根据业务层传递的数据进行UI渲染。
  2. 状态管理
    • 采用ProviderBloc等状态管理模式,管理应用的状态,使视图层能够根据状态变化进行更新,同时避免视图层之间的状态传递混乱。

关键代码片段

  1. 使用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;
    }
  }
}
  1. 业务层调用数据层接口并处理数据示例
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;
  }
}
  1. 视图层使用状态管理展示数据示例(以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++;
  }
}