記一次排查Flutter中預期外rebuild的過程

madlife0412發表於2021-06-01

背景

在我的flutter專案中,從A元件導航到B元件後,B元件在軟鍵盤彈起與收起的時候,A元件會不斷呼叫didUpdateWidgetbuild

初步排查

起初以為是路由的問題,經過排查後發現,Navigator確實存在歷史問題,會導致oldWidgetrebuild。 在1.17版本之後,這個問題已經被修復了,開發者不再需要額外的工作即可避免。

相關分析

發現端倪

繼續排查了很多地方,本以為可能出現問題的選單元件、MediaQuery的不合適的呼叫等等,都沒有發現問題。 開始從下往上思考:如果元件本身沒有呼叫setState,沒有繼承InheritedWidget,那發生預期外的生命週期函式呼叫,一定是它的context在其他地方發生預期外的使用了

找到凶手

搜尋A元件裡所有用到context的地方,果不其然,凶手找到了:

precacheImage(NetworkImage(Constants.bgUrl), context);
複製程式碼

進入precacheImage的原始碼後,很容易找到context被註冊到了MediaQuery.maybeOf,剩下的就很好理解了: MediaQuery繼承自InheritedWidget; 軟鍵盤呼叫時,MediaQueryData會變化,所有通過MediaQuery.maybeOfMediaQuery.of註冊的元件都會更新。

總結

  • 深入理解Flutter的生命週期和更新邏輯,在遇到相關的問題時總是能從原始碼和原理上找到解決辦法。
  • 保護好元件的context

相關文章