今天在做一個(gè)需求,動(dòng)態(tài)更新底部導(dǎo)航菜單BottomNavigationBar。本來(lái)很簡(jiǎn)單的一個(gè)需求卻踩了一個(gè)坑,特此記錄一下。
問(wèn)題:
在更新菜單item數(shù)據(jù)后,通過(guò)setState((){})刷新 BottomNavigationBar
_buildNavigationBar() {
return BottomNavigationBar(
type: BottomNavigationBarType.fixed,
unselectedFontSize: 10,
selectedFontSize: 10,
backgroundColor: Colors.white,
items: barItemList,
currentIndex: _index,
onTap: (value) async {
},
);
}
這時(shí)候直接報(bào)錯(cuò):
RangeError (index): Invalid value: Not in inclusive range 0..1: 2
字面意思是index越界了。
但通過(guò)打印確認(rèn)了index的值并沒(méi)有越界,那是哪里不對(duì)?
原因:
分析BottomNavigationBar源碼后發(fā)現(xiàn)只有在它的initState()才會(huì)去更新數(shù)據(jù),
@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((){})并沒(méi)有重新執(zhí)行initState(),只是重新build(),所以BottomNavigationBar拿到的items長(zhǎng)度還是舊的數(shù)據(jù)。
解決:
確定了原因解決方法就比較清晰了,就是需要讓BottomNavigationBar重新創(chuàng)建,執(zhí)行它的didUpdateWidget(),方法是我們可以改變它的key來(lái)觸發(fā)。
首先給它設(shè)置一個(gè)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 {
},
);
}
在更新完數(shù)據(jù),只需要修改它的key就可以:
// 更新數(shù)據(jù)完成,刷新UI:
_navBarKey = UniqueKey();
以此類推,要讓其他Widget重新創(chuàng)建也可以用同樣的方法。
最后,補(bǔ)充說(shuō)明一下UniqueKey():
UniqueKey是Flutter框架中的一個(gè)特殊類型,用于為Widget對(duì)象生成唯一的標(biāo)識(shí)符。它是Key類的子類,用于標(biāo)識(shí)Widget樹中的一個(gè)節(jié)點(diǎn),并確保它是唯一的。