【Flutter】解决BottomNavigationBar动态更新RangeError问题

今天在做一个需求,动态更新底部导航菜单BottomNavigationBar。本来很简单的一个需求却踩了一个坑,特此记录一下。

问题:

在更新菜单item数据后,通过setState((){})刷新 BottomNavigationBar

  _buildNavigationBar() {
    return BottomNavigationBar(
      type: BottomNavigationBarType.fixed,
      unselectedFontSize: 10,
      selectedFontSize: 10,
      backgroundColor: Colors.white,
      items: barItemList,
      currentIndex: _index,
      onTap: (value) async {
      },
    );
  }

这时候直接报错:

RangeError (index): Invalid value: Not in inclusive range 0..1: 2

字面意思是index越界了。
但通过打印确认了index的值并没有越界,那是哪里不对?

原因:

分析BottomNavigationBar源码后发现只有在它的initState()才会去更新数据,

  @override
  void didUpdateWidget(BottomNavigationBar oldWidget) {
    super.didUpdateWidget(oldWidget);

    // No animated segue if the length of the items list changes.
    if (widget.items.length != oldWidget.items.length) {
      _resetState();
      return;
    }
    ……

但setState((){})并没有重新执行initState(),只是重新build(),所以BottomNavigationBar拿到的items长度还是旧的数据。

解决:

确定了原因解决方法就比较清晰了,就是需要让BottomNavigationBar重新创建,执行它的didUpdateWidget(),方法是我们可以改变它的key来触发。
首先给它设置一个key:

  var _navBarKey = UniqueKey();

  _buildNavigationBar() {
    return BottomNavigationBar(
      key: _navBarKey,
      type: BottomNavigationBarType.fixed,
      unselectedFontSize: 10,
      selectedFontSize: 10,
      backgroundColor: Colors.white,
      items: barItemList,
      currentIndex: _index,
      onTap: (value) async {
      },
    );
  }

在更新完数据,只需要修改它的key就可以:

//  更新数据完成,刷新UI:
_navBarKey = UniqueKey();

以此类推,要让其他Widget重新创建也可以用同样的方法。

最后,补充说明一下UniqueKey():

UniqueKey是Flutter框架中的一个特殊类型,用于为Widget对象生成唯一的标识符。它是Key类的子类,用于标识Widget树中的一个节点,并确保它是唯一的。

End

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容