今天在作客戶的項目時,有一個需求是App上要顯示遠端的圖片,而遠端的圖片有可能會更新,但圖片名不變。前端
在react-native中,顯示圖片是用的自帶的Image組件,你們都知道react在更新組件以前都會判斷props或state是否有改變,當有改變時纔會更新,不然不會刷新頁面。java
那問題就來了,遠端的圖片名不變,傳入Image組件的props就不會變,Image組件就不會刷新,當遠端的圖片內容被修改以後,該怎麼讓前端同時顯示最新的圖片呢?react
在遇到這個問題時,我是先在網上找到一個方法,說是兩個同名的圖片,若是內容不同,則轉成base64以後也不同,能夠以這種方式讓前端刷新,android
我當時也以爲這是一個好方法,因而我寫了以下代碼:react-native
let buffer = await akita.get('/圖片地址').buffer(); let base64 = 'data:p_w_picpath/jpeg;base64,' + buffer.toString('base64'); render(){ ... <Image source={{uri:this.state.base64}}/> ... }
結果然的能夠更新了,我興奮的打了一個release版放到真機上去測試,但沒過兩秒,app居然閃退了,api
瞬間感受不會再愛了。bash
而後我開始輸出日誌查看,特別註明:不管是debug版仍是release版,下面這條命令都能查看到輸出日誌,但.....具體狀況仍是大家本身試一下吧,反正不會爆炸。網絡
adb logcat androidRuntime:E/
而後就輸入了不少日誌,全是關於java的,我都快哭了,最終,在日誌裏找到一個報錯的輸出:app
FATAL EXCEPTION: mqt_js Process: com.appscreen, PID: 28053 java.lang.RuntimeException: Error calling function: RCTDeviceEventEmitter:emit at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method) at android.os.Handler.handleCallback(Handler.java:733) at android.os.Handler.dispatchMessage(Handler.java:95) at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(MessageQueueThreadHandler.java:31) at android.os.Looper.loop(Looper.java:136) at com.facebook.react.bridge.queue.MessageQueueThreadImpl$3.run(MessageQueueThreadImpl.java:196) at java.lang.Thread.run(Thread.java:841) Caused by: java.lang.RuntimeException: Failed to create String from JSON: ... 7 more Force finishing activity com.appscreen/.MainActivity D/dalvikvm(28053): GC_CONCURRENT freed 484K, 12% free 4735K/5344K, paused 5ms+3ms, total 50ms D/dalvikvm(28053): WAIT_FOR_CONCURRENT_GC blocked 31ms D/dalvikvm(28053): WAIT_FOR_CONCURRENT_GC blocked 42ms D/dalvikvm(28053): WAIT_FOR_CONCURRENT_GC blocked 12ms D/dalvikvm(28053): WAIT_FOR_CONCURRENT_GC blocked 14ms D/dalvikvm(28053): WAIT_FOR_CONCURRENT_GC blocked 35ms D/dalvikvm(28053): WAIT_FOR_CONCURRENT_GC blocked 27ms D/dalvikvm(28053): GC_FOR_ALLOC freed 173K, 9% free 4985K/5452K, paused 21ms, total 22ms D/dalvikvm( 1014): GC_FOR_ALLOC freed 292K, 22% free 7064K/9032K, paused 65ms, total 65ms I/Choreographer(28053): Skipped 37 frames! The application may be doing too much work on its main thread. I/Process (28053): Sending signal. PID: 28053 SIG: 9 W/InputDispatcher( 1014): channel '41b9ec38 com.appscreen/com.appscreen.MainActivity (server)' ~ Consumer closed input channel or an error occurred. events=0x9 E/InputDispatcher( 1014): channel '41b9ec38 com.appscreen/com.appscreen.MainActivity (server)' ~ Channel is unrecoverably broken and will be disposed! W/InputDispatcher( 1014): Attempted to unregister already unregistered input channel '41b9ec38 com.appscreen/com.appscreen.MainActivity (server)' I/ActivityManager( 1014): Process com.appscreen (pid 28053) has died. I/WindowState( 1014): WIN DEATH: Window{41b9ec38 u0 com.appscreen/com.appscreen.MainActivity} Caught a RuntimeException from the binder stub implementation. java.lang.NullPointerException at android.inputmethodservice.IInputMethodWrapper.setSessionEnabled(IInputMethodWrapper.java:280) at com.android.internal.view.IInputMethod$Stub.onTransact(IInputMethod.java:129) at android.os.Binder.execTransact(Binder.java:404) at dalvik.system.NativeStart.run(Native Method)
看到這,我已經心涼了,這是什麼錯,徹底和本身寫的代碼對不上號啊,dom
可是沒辦法,只能硬着頭皮去網上扒拉,但願能找到答案,
結果是........讓人很失望,我沒有找到怎麼解決這個bug。
後來實在感受弄不出來了,只好去請教大神,對話以下:
我:大神,我這有個問題幫我看一下唄,
大神: RN我也沒搞過啊,
........我很心涼,這時大神又問了一句
大神: 你什麼需求,
我: Q#$^#$&#@@&@(見文章開頭),
大神:這還很差辦,既然請求的是網絡圖片,你給圖片地址後面加隨機參數不就好了。
。。。。。。
好吧,大神就是大神,一句話讓我網上扒拉資料的4個小時變成了一堆廢渣。。
因而我就按大神說的來作,
randomString() { len = 6; var $chars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefhijklmnprstuvwxyz0123456789'; var maxPos = $chars.length; var pwd = ''; for (let i = 0; i < len; i+=1) { pwd += $chars.charAt(Math.floor(Math.random() * maxPos)); } return pwd; } render(){ let imgUrl = SERVER_HOST + '/pic/' + item.pic + '.jpg?code=' + this.randomString(); ... <Image source={{uri:imgUrl}}/> ... }
好吧,不得再也不次感嘆一聲,大神就是大神,一句話讓我以前寫的代碼全白費,又同時解決了個人問題。
在此,感謝大神。
---------------------------下面是重點----------------------------------------------
想讓圖片刷新,就必須保證傳入 Image 組件的props是不同的,基於文件名相同,則只能:
1,使用base64,不一樣圖片內容的base64是不同的,但這種方法可能會遇見我上面說的坑。
2,由於是網絡圖片,因此,每個圖片地址就像當於一個API接口,是能夠帶參數的。
文件名後面跟上一些參數後,無論參數是什麼,api接口沒有變就能獲得圖片內容,同時,由於參數不同,最終傳入Image組件的props也不同,這樣就能讓Image組件刷新了。