Flutter中Firebase Realtime Database监听异步调用致APP冻结求助
解决Firebase实时数据监听导致APP冻结的问题
你的代码存在两个核心问题会引发UI冻结:
- 每次数据更新时直接往
sensorList追加数据,未清空旧数据,随着监听次数增加,列表体积持续膨胀,渲染时占用大量主线程资源 - 数据解析、列表修改全在主线程执行,若数据量较大,会直接阻塞UI刷新
基础修正方案
先解决数据累积问题,同时优化状态更新逻辑:
late List<Data> sensorList = []; @override void initState() { super.initState(); _tooltipBehavior = TooltipBehavior(enable: true); getSensorData(); } void getSensorData() { _database.child(_path).orderByKey().limitToLast(10).onValue.listen((data) { debugPrint("${data.snapshot.value}"); final tempList = <Data>[]; if (data.snapshot.value != null) { final sensorData = Map<String, dynamic>.from( data.snapshot.value as Map<dynamic, dynamic>, ); sensorData.forEach((key, value) { final nextData = Data.fromRTDB(Map<String, dynamic>.from(value)); tempList.add(nextData); }); } // 统一更新状态,避免频繁setState setState(() { sensorList = tempList; }); }); }
进阶优化(针对复杂解析逻辑)
如果Data.fromRTDB的解析逻辑比较复杂,建议用compute将解析操作移到后台隔离线程,彻底避免主线程阻塞:
late List<Data> sensorList = []; @override void initState() { super.initState(); _tooltipBehavior = TooltipBehavior(enable: true); getSensorData(); } // 抽离解析逻辑为顶层函数(compute要求函数是顶层或static) List<Data> parseSensorData(Map<String, dynamic> sensorData) { final tempList = <Data>[]; sensorData.forEach((key, value) { final nextData = Data.fromRTDB(Map<String, dynamic>.from(value)); tempList.add(nextData); }); return tempList; } void getSensorData() { _database.child(_path).orderByKey().limitToLast(10).onValue.listen((data) async { debugPrint("${data.snapshot.value}"); List<Data> tempList = []; if (data.snapshot.value != null) { final sensorData = Map<String, dynamic>.from( data.snapshot.value as Map<dynamic, dynamic>, ); // 后台线程执行解析 tempList = await compute(parseSensorData, sensorData); } setState(() { sensorList = tempList; }); }); }
内容的提问来源于stack exchange,提问作者Johan Scheepers
相关产品推荐
相关产品推荐

