react-native之远程图片修改后APP不更新

今天在作客户的项目时,有一个需求是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组件刷新了。

相关文章
相关标签/搜索