背景
在我的flutter
專案中,從A元件導航到B元件後,B元件在軟鍵盤彈起與收起的時候,A元件會不斷呼叫didUpdateWidget
和build
。
初步排查
起初以為是路由的問題,經過排查後發現,Navigator
確實存在歷史問題,會導致oldWidget
的rebuild
。
在1.17版本之後,這個問題已經被修復了,開發者不再需要額外的工作即可避免。
發現端倪
繼續排查了很多地方,本以為可能出現問題的選單元件、MediaQuery
的不合適的呼叫等等,都沒有發現問題。
開始從下往上思考:如果元件本身沒有呼叫setState
,沒有繼承InheritedWidget
,那發生預期外的生命週期函式呼叫,一定是它的context
在其他地方發生預期外的使用了。
找到凶手
搜尋A元件裡所有用到context
的地方,果不其然,凶手找到了:
precacheImage(NetworkImage(Constants.bgUrl), context);
複製程式碼
進入precacheImage
的原始碼後,很容易找到context
被註冊到了MediaQuery.maybeOf
,剩下的就很好理解了:
MediaQuery
繼承自InheritedWidget
;
軟鍵盤呼叫時,MediaQueryData
會變化,所有通過MediaQuery.maybeOf
和MediaQuery.of
註冊的元件都會更新。
總結
- 深入理解
Flutter
的生命週期和更新邏輯,在遇到相關的問題時總是能從原始碼和原理上找到解決辦法。 - 保護好元件的
context
。