本篇文章向大家分享了一個關於Fix一個隨機重現的鍵盤issue後的思考,很有意義,感興趣的朋友可以看一下
最近花了近一周fix了一個移動端的bug,是個很有趣的bug,大概是這樣的。這是一個比較長的故事,有興趣的可以一直看。
是一個什麼樣的bug
bug的表現是在一款tablet端應用使用很久之後,第一,在輸入框內輸入一些內容後,點擊done/search,第二,然後點擊頁面的一些空白地區,軟鍵盤彈出,並且游標focus在最近輸入過的輸入框內。
此時應用對使用者行為的響應會讓使用者很疑惑和費解。
總結,它有如下幾個特點
如何去修複這個bug
第一步 試圖穩定重新
我們先是試圖去找一個最小的使用者journey去複現這個bug,當時運氣比較好,花了大概半天時間找到了一條最小的重現路徑。
不說業務背景,簡單介紹下應用的頁面邏輯。
我們的應用在登入之後有一個home頁面,home頁面存在三個tab可以滑動或者點擊切換,在tab頁面之上還存在一些功能菜單,其中某個功能菜單menuA可以點擊跳到另一個新的帶有一個輸入框的頁面。
頁面大概如下,不是專業ux很醜勿見怪。
我們發現的一條可以快速重現的路徑是
然後軟鍵盤就出來了。
第二步 試圖從代碼部分找到為什麼最小情境會出現問題
找到一個最小重現路徑之後,我們可以從代碼裡面找找為什麼會出現這個問題。
因為這個bug在應用重啟後沒有,我們懷疑的方向就定位在render的問題,大機率是出在組件上。
我們中間有幾個猜測
最後發現貌似都不是,這個時候和組內另外一個同事pair,她發現在請求比較多的時候容易有問題,中間還懷疑過網路請求處理導致的。這個懷疑其實不大對,但是確實為我們找到了一條路。
我們最後發現我們所有的網路請求都在請求結果返回之前在頁面出現一層蒙版mask以及一個類似web裡面spinner(在RN裡面是ActivityIndicator)的loading提示符號,這個部分是會影響頁面render的。
而把這部分去掉(在請求到達之前不出現蒙層),這個bug就沒有了,這個發現當時還是讓人很震驚的以及疑惑的,因為似乎找到了一部分原因但我們還是沒搞清楚為什麼。
第三步 嘗試修複(未弄清根本原因的情況下)
有了這個思路的提示,我們試圖嘗試修複。按照業務需求,我們不能取消ActivityIndicator的使用,因為給使用者適當的提示這個確實很有必要。
我們試圖去修改mask的實現,在老的裡面我們使用了一個第三方的RN組件react-native-root-siblings來協助我們在root同級插入一個兄弟元素顯示我們的loading提示符號。
一般在發完請求請求結果未到達之前,我們就插入一個新的同級兄弟元素,請求完成後就刪除掉它。當時懷疑因為這部分反覆的修改頁面的元素結構,就把new-destory的邏輯換成了new-update的邏輯,減少了元素的修改。update的時候只是去讓ActivityIndicator不出現似乎被hide了。
第四步 測試bug是否還能重現
我們希望通過減少頁面元素反覆的刪除建立,來fix這個bug,結果怎麼樣呢?
居然神奇的很難複現了,我們很開心,雖然還是沒弄懂原因。
後面QA說在真機上還是遇到了幾次,讓我們更是費解,費解的是出現的機率確實變少了,但為啥還會出現?
第五步 分析bug產生的根本原因
這個時候我們需要瞭解bug產生的真正原因了。
我們重新回到這個bug的表現,為什麼點擊空白地區會觸發TextInput的focus方法?我們嘗試做了這樣幾件事情。
除了在代碼邏輯裡面少量的通過綁定ref然後觸發.focus方法(因為是少量出現,不符合我們這個bug一出現所有input都受影響的情景,快速排除不是這部分原因),我們發現在RN提供的TextInput組件裡面也有很多地方會調用到focus方法。