MST

星途 面试题库

面试题:Flutter异步操作与Stream结合处理复杂业务场景

在一个电商应用中,有这样一个场景:用户可以在商品列表页面进行筛选操作(如筛选价格范围、商品类别等),每次筛选后,需要从服务器获取新的数据并实时更新列表。同时,在获取数据过程中,如果网络出现波动,要能够及时处理并提示用户。请阐述如何利用Flutter的异步操作(如Future等)与Stream来实现该功能,包括数据请求、错误处理以及UI更新机制。
32.5万 热度难度
前端开发Flutter

知识考点

AI 面试

面试题答案

一键面试

1. 数据请求

使用 Future 来处理数据请求。可以封装一个函数,例如 fetchProductData,它接收筛选条件(如价格范围、商品类别等)作为参数,并返回一个 Future。在这个函数内部,使用 http 或其他网络请求库向服务器发送请求。

import 'package:http/http.dart' as http;
import 'dart:convert';

Future<List<dynamic>> fetchProductData({
  double? minPrice,
  double? maxPrice,
  String? category,
}) async {
  // 构建请求URL
  Uri url = Uri.parse('https://your-server-url/api/products');
  Map<String, String> queryParameters = {};
  if (minPrice != null) queryParameters['minPrice'] = minPrice.toString();
  if (maxPrice != null) queryParameters['maxPrice'] = maxPrice.toString();
  if (category != null) queryParameters['category'] = category;
  url = url.replace(queryParameters: queryParameters);

  // 发送请求
  http.Response response = await http.get(url);

  if (response.statusCode == 200) {
    return json.decode(response.body);
  } else {
    throw Exception('Failed to load products');
  }
}

2. 错误处理

fetchProductData 函数中,如果请求失败(状态码非200),抛出异常。在调用这个 Future 的地方,使用 try - catch 块来捕获异常并处理。

try {
  List<dynamic> products = await fetchProductData(minPrice: 10, maxPrice: 100, category: 'electronics');
  // 处理成功获取的数据,更新UI
} catch (e) {
  // 处理错误,提示用户
  print('Error: $e');
}

3. UI更新机制

使用 StatefulWidget 来管理UI状态。在 State 类中定义一个变量来存储商品列表数据。当数据请求成功时,更新这个变量,并调用 setState 方法来通知Flutter框架重新构建UI。

class ProductListPage extends StatefulWidget {
  @override
  _ProductListPageState createState() => _ProductListPageState();
}

class _ProductListPageState extends State<ProductListPage> {
  List<dynamic> _products = [];
  bool _isLoading = false;

  @override
  void initState() {
    super.initState();
    _fetchProducts();
  }

  Future<void> _fetchProducts() async {
    setState(() {
      _isLoading = true;
    });
    try {
      List<dynamic> products = await fetchProductData(minPrice: 10, maxPrice: 100, category: 'electronics');
      setState(() {
        _products = products;
        _isLoading = false;
      });
    } catch (e) {
      setState(() {
        _isLoading = false;
      });
      // 可以在这里弹出一个对话框提示用户网络波动等错误
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Network error: $e')));
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Product List')),
      body: _isLoading
         ? Center(child: CircularProgressIndicator())
          : ListView.builder(
              itemCount: _products.length,
              itemBuilder: (context, index) {
                // 构建商品列表项
                return ListTile(title: Text(_products[index]['name']));
              },
            ),
    );
  }
}

4. 使用Stream处理网络波动

可以使用 Stream 来监听网络状态变化。引入 connectivity_plus 库来获取网络连接状态。

import 'package:connectivity_plus/connectivity_plus.dart';

class NetworkMonitor {
  static final NetworkMonitor _instance = NetworkMonitor._();
  late StreamSubscription<ConnectivityResult> _subscription;
  final StreamController<ConnectivityResult> _controller = StreamController<ConnectivityResult>.broadcast();

  NetworkMonitor._() {
    _subscription = Connectivity().onConnectivityChanged.listen((ConnectivityResult result) {
      _controller.add(result);
    });
  }

  Stream<ConnectivityResult> get networkStream => _controller.stream;

  void dispose() {
    _subscription.cancel();
    _controller.close();
  }
}

ProductListPage 中监听这个 Stream,当网络状态变化时进行相应处理。

class _ProductListPageState extends State<ProductListPage> {
  //... 其他代码

  @override
  void initState() {
    super.initState();
    _fetchProducts();
    NetworkMonitor().networkStream.listen((ConnectivityResult result) {
      if (result == ConnectivityResult.none) {
        // 网络断开,提示用户
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Network disconnected')));
      } else {
        // 网络恢复,重新获取数据
        _fetchProducts();
      }
    });
  }

  @override
  void dispose() {
    NetworkMonitor().dispose();
    super.dispose();
  }

  //... 其他代码
}

通过以上步骤,利用Flutter的异步操作(Future)与 Stream 实现了电商应用中商品列表筛选、数据请求、错误处理以及UI更新机制,并处理了网络波动情况。