寫業務代碼怎麼了

有時跟同行的朋友們聊天,多少會聊到一些工作上的事情,比如你是寫底層的呢還是寫業務,寫業務搞不搞框架啊,啥你還在寫頁面?

這種問題一般我都不喜歡正面回答,就說我們用 RN。如果對方正好也寫頁面,並且還業務繁重,就會開始巴拉巴拉地吐槽。

如果對方已經不寫頁面了,此時會陷入一片寂靜。

這樣的情況經歷幾次以後(其實也就一兩次),讓我開始思考一個問題,寫業務怎麼了,頁面得罪你了嗎?

前兩天在改頁面,要把 RN 提供的圖片組件替換成我們架構組封裝的組件。發現有一個小圖標,偶爾會在頁面第一次打開的時候不顯示,把其它幾張圖片注釋掉後,會恢復了正常。

圖片是 URL 載入的,我第一反應是網路問題,而且小圖標沒顯示也不影響功能,不爽的話返回重進好了。如果測試反饋這個問題,就說「是你手機網路不好」。

後面想了想覺得有點不對勁:

1. 公司網路不賴,不至於幾 K 的圖標載入失敗;

2. 圖片會有內存緩存,App 只是 Hot Reloading,為什麼就不顯示了;

全部替回 RN 圖片組件,顯示又恢復正常了,恐怕是新組件有 bug 吧……

查閱了下內部實現,發現只是處理了下大小和提供默認圖片,並不會影響圖片的顯示。

那問題肯定來源於 RN 了,然後開始翻 RN 原生 Image 的實現,發現一個令我很納悶的事情,原生端居然沒有做原始圖片數據緩存。

雖然有一個用於圖片緩存的類,但它在網路請求之後才使用,利用 URL 和圖片本身的信息哈希,讀取緩存中解碼後的數據,如果沒有命中,會把圖片解碼,然後寫入緩存。

每次刷新都會發起網路請求,網路開銷這麼大不做緩存,反而在這之後緩存解碼的數據是為什麼?

網上查了一下發現 RN 其實有提供圖片的緩存。在最新版本 RN 中為 JS 端提供了查詢緩存的介面,再看原生實現才發現原來是利用了 HTTP 緩存。

顯示一張網路圖片,一般第一反應是挑一個圖片庫,很少有意識的去思考利用 Foundation 提供的功能。

當然系統層的緩存也是在 HTTP 協議之上的封裝,如果要再細緻的考慮為什麼圖片會被緩存,而數據介面卻不會,就要涉及到 HTTP 緩存控制了。

既然圖片原始數據已經有緩存,為什麼 RN 還要對圖片解碼後的數據做緩存,圖片的解碼開銷能有多大?

帶著這個問題,發現了一個牛逼的圖片庫 FastImageCache,對圖片顯示的優化做到了極致。國內圖片優化寫得不錯的文章,至少有幾句是從他的 README 翻譯過來的(當然 YY 大神的除外)。

它主要對圖片從磁碟讀取到顯示的過程做了三點優化:

1. 使用 mmap 內存映射,省去了從磁碟讀取數據時,需要將數據從內核空間拷貝到用戶空間的過程;

2. 將解碼後的圖片數據直接緩存到磁碟,免去應用重啟需要再解碼;

3. 生成位元組對齊的圖片數據,防止 CoreAnimation 在渲染時再做位元組對齊的拷貝。

到這裡關於 RN 圖片顯示的過程已經了解的差不多了。上面涉及到的知識如果要深挖下去還是能有很多收穫的。

再回到圖片不顯示的問題(好幾天過去了),怎麼都復現不了了……

我猜測這多半是 RN 在線程式控制制上比較敏感,多調用幾層函數有時會被干擾,但這已經不重要了,面對茫茫的知識盲區,焦慮的心情都沒了。

整個過程還是挺開心,這或許也是寫業務的樂趣所在。大多數人不喜歡寫業務可能在於業務的多變,但是不管怎麼變它都有一個不變的量,那就是需求會變。

既然需求始終要變,寫了也是白寫,直接放棄不寫是一種選擇,還有一種是去分析需求的變化頻率,編程的顆粒度能細分到比特,需求可以嗎?

當我們知道哪些會頻繁變動的時候,就可以將它們隔離,這時候可能需要一種設計模式,一旦我們找到某種模式能滿足我們的需求,收穫會比單純的為了掌握某種設計模式而看書來的多。

寫業務還有很重要的一點,成就感會很強烈。頁面離用戶最近,用戶如果覺得好用我們可以很坦然地說是自己寫的,如果只是提供了個組件,我會不好意思說。


人生難得幾回頭,掃碼關注有盼頭。


推薦閱讀:

TAG:程序員 | iOS開發 |