淺析 Flutter TabController 監(jiān)聽調(diào)用兩次

在開發(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è)方法。


圖三
通過前面的分析我們知道了,duration != null && duration > Duration.zero ,那我們來看下 if 語句里面的代碼,我們發(fā)現(xiàn) notifyListeners() 調(diào)用了2次,在動(dòng)畫開始前后各調(diào)了一次。 那我們?cè)诳纯?notifyListeners 方法。
圖四

圖五

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} ");
        }
      });
ok咯
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容