You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter如何从数据库获取值初始化并更新RangeSlider组件

Flutter RangeSlider 动态加载接口数据适配方案

问题根因

  • 原代码直接在类成员初始化位置读取异步返回的data变量,此时接口请求还未完成,data为null,无法正确赋值
  • 「Null check operator used on a null value」报错来自三个常见场景:
    • 本地缓存读取的UsrID为空时直接传入请求参数
    • 接口返回数据结构不符合预期时,直接读取data[0]下的字段触发空引用/数组越界
    • 异步请求完成时页面已销毁,强制调用setState触发空异常

修改方案

核心逻辑

保留_currentRangeValues的默认固定值作为加载兜底,不要在类初始化阶段读取未返回的接口数据;在接口请求成功、数据校验通过后再给滑块变量赋值,同时加全链路空判断;接口加载过程中显示加载态,避免用户在数据未就绪时操作滑块,从交互层面规避异常。

修改后完整可运行代码

class Age extends StatefulWidget {
  Age({Key? key}) : super(key: key);

  @override
  _Age createState() => _Age();
}

class _Age extends State<Age> {
  String? UsrID;
  var data;
  // 保留默认值作为加载中、加载失败的兜底
  RangeValues _currentRangeValues = const RangeValues(30, 70);
  // 加载状态标记
  bool _isLoading = true;

  @override
  void initState() {
    super.initState();
    // 初始化读取本地用户ID
    UsrID = Auth.prefs?.getString('usrid');
    getData();
  }

  Future<void> getData() async {
    // 用户ID为空直接终止请求,避免无效调用
    if (UsrID == null) {
      if (mounted) {
        setState(() {
          _isLoading = false;
        });
      }
      return;
    }

    try {
      var res = await http.get(
        Uri.https(
          'www.*******.com',
          '/index.php',
          {'act': 'profile', 'UsrID': UsrID!},
        ),
      );
      // 接口响应成功才解析数据
      if (res.statusCode == 200) {
        data = jsonDecode(res.body);
        // 逐层校验返回结构合法性,避免空引用
        if (data is List && data.isNotEmpty) {
          final firstItem = data[0];
          if (firstItem.containsKey('age1') && firstItem.containsKey('age2')) {
            // 兼容接口返回int、String、double类型的数值
            final start = double.tryParse(firstItem['age1'].toString()) ?? 30;
            final end = double.tryParse(firstItem['age2'].toString()) ?? 70;
            // 边界值校验:起始值小于结束值,且在滑块0-100的取值范围内
            if (start >= 0 && end <= 100 && start < end) {
              _currentRangeValues = RangeValues(start, end);
            }
          }
        }
      }
    } catch (e) {
      // 捕获网络、解析异常,避免页面崩溃
      print('年龄配置加载失败: $e');
    } finally {
      // 页面未销毁时才刷新状态
      if (mounted) {
        setState(() {
          _isLoading = false;
        });
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 24),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Text(
              'Age',
              style: TextStyle(
                color: Color(0xff2c3531),
              ),
            ),
            addVerticalSpace(10),
            _isLoading
                ? const Center(child: CircularProgressIndicator())
                : RangeSlider(
                    activeColor: const Color(0xff8f9df2),
                    inactiveColor: const Color(0xff9a9a9a),
                    values: _currentRangeValues,
                    min: 0,
                    max: 100,
                    divisions: 5,
                    labels: RangeLabels(
                      _currentRangeValues.start.round().toString(),
                      _currentRangeValues.end.round().toString(),
                    ),
                    onChanged: (RangeValues values) {
                      setState(() {
                        _currentRangeValues = values;
                      });
                      // 若需要滑动后同步更新到数据库,在此处调用更新接口即可
                    },
                  ),
          ],
        ),
      ),
    );
  }
}

关键注意点

  • 不要在类成员初始化位置直接读取异步方法返回的变量,Dart中类成员初始化是同步执行的,此时异步请求还未返回结果,必然拿到null
  • 所有外部传入的数据(接口返回、本地缓存)都要做空判断和类型兼容处理,不要直接强转、直接读取数组/字典字段
  • 异步方法中调用setState前必须判断mounted属性,避免页面销毁后触发状态更新抛出异常

内容的提问来源于stack exchange,提问作者RAF Algowid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 21:24:22