在開發(fā)過程中我們經(jīng)常會(huì)用到 TabBar 、TabBarView ,當(dāng)我們滑動(dòng)TabBarView 組件時(shí),TabController 的監(jiān)聽方法調(diào)用了1次;但當(dāng)你點(diǎn)擊 TabBar 的 Tab 時(shí),TabController 的監(jiān)聽方法會(huì)調(diào)用了2次,很奇怪??,下面我們就來看看是什么原因以及解決辦法。
問題
TabController 是繼承至 ChangeNotifier,當(dāng)我們調(diào)用 tabController.animateTo(index) 切換 tab 時(shí),發(fā)現(xiàn) addListener 監(jiān)聽方法調(diào)用了2次。
tabController = TabController(length: tabs.length, vsync: this)
..addListener(() {
print("監(jiān)聽切換tab ${tabController.index}");
});
tabController.animateTo(index); // 切換tab

原因


我們先來看下[圖一] animateTo 方法,通過[圖二] TabController 的初始化方法,我們知道 duration != null && duration > Duration.zero_animationDuration!=null&&duration > Duration.zero 。animateTo 方法里調(diào)用了 _changeIndex() ,我們接下來重點(diǎn)看看這個(gè)方法。



notifyListeners 方法里執(zhí)行了 _listeners 集合里的方法,通過查看[圖五] addListener 方法知道,_listeners 集合里面的方法 就是tabController 通過 addListener() 添加的 VoidCallback 監(jiān)聽方法。到此真相也就大白,圖三的 notifyListeners() 調(diào)用了2次 ,也就是通過addListener() 添加的監(jiān)聽方法調(diào)了2次,所以我們會(huì)看到切換tab時(shí) 打印了2次日志。原因找到了,接下來我們看看解決辦法。
解決

其實(shí) _changeIndex 方法已經(jīng)給了我們解訣辦法,當(dāng)?shù)谝淮握{(diào)用notifyListeners() 時(shí),_indexIsChangingCount = 1;當(dāng)?shù)诙握{(diào)用notifyListeners() 時(shí),_indexIsChangingCount = 0,所有我們可以通過判斷 _indexIsChangingCount 來決解問題,當(dāng)然_indexIsChangingCount 是私有屬性,我們不可以直接使用的,但是TabController 提供了 indexIsChanging 屬性 {bool get indexIsChanging => _indexIsChangingCount != 0;} ,
問題解決:
tabController = TabController(length: tabs.length, vsync: this)
..addListener(() {
// or (tabController.indexIsChanging)
if (!tabController.indexIsChanging) {
print("監(jiān)聽切換tab ${tabController.index} ");
}
});
