react-native-fast-image 由于source的uri非法而奔溃

React Native 2019-12-18 阅读 198 评论 0

react-native 的 Image 组件加载性能低,未能很好地实现缓存,存在加载闪烁的问题。react-native-fast-image是一个native库,可以解决这些问题,是 Image 组件的替代品。 FastImage 在iOS上是使用 SDWebImage(IOS),Android上是Glide(Android),这2个项目在github都是4K以上的star,使用的开发者很多。

问题描述

如果给FastImage 传的source对象包含非法的uri:

{ uri: 'INVALID_URL' }

比如:

<FastImage source={{uri: "/logo.png"}} />

在安卓上运行,将出现以下异常,但是在ios上却是正常的。

com.facebook.react.bridge.JSApplicationIllegalArgumentException: Error while updating property 'source' of a view managed by: FastImageView
	at com.facebook.react.uimanager.ViewManagersPropertyCache$PropSetter.updateViewProp(ViewManagersPropertyCache.java:98)
	at com.facebook.react.uimanager.ViewManagerPropertyUpdater$FallbackViewManagerSetter.setProperty(ViewManagerPropertyUpdater.java:131)
	at com.facebook.react.uimanager.ViewManagerPropertyUpdater.updateProps(ViewManagerPropertyUpdater.java:51)
	at com.facebook.react.uimanager.ViewManager.updateProperties(ViewManager.java:46)
	at com.facebook.react.uimanager.NativeViewHierarchyManager.createView(NativeViewHierarchyManager.java:268)
	at com.facebook.react.uimanager.UIViewOperationQueue$CreateViewOperation.execute(UIViewOperationQueue.java:198)
	at com.facebook.react.uimanager.UIViewOperationQueue$DispatchUIFrameCallback.dispatchPendingNonBatchedOperations(UIViewOperationQueue.java:1036)
	at com.facebook.react.uimanager.UIViewOperationQueue$DispatchUIFrameCallback.doFrameGuarded(UIViewOperationQueue.java:1007)
	at com.facebook.react.uimanager.GuardedFrameCallback.doFrame(GuardedFrameCallback.java:29)
	at com.facebook.react.modules.core.ReactChoreographer$ReactChoreographerDispatcher.doFrame(ReactChoreographer.java:172)
	at com.facebook.react.modules.core.ChoreographerCompat$FrameCallback$1.doFrame(ChoreographerCompat.java:84)
	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:984)
	at android.view.Choreographer.doCallbacks(Choreographer.java:798)
	at android.view.Choreographer.doFrame(Choreographer.java:727)
	at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:972)
	at android.os.Handler.handleCallback(Handler.java:790)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loop(Looper.java:192)
	at android.app.ActivityThread.main(ActivityThread.java:6906)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:550)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:828)
Caused by: java.lang.reflect.InvocationTargetException
	at java.lang.reflect.Method.invoke(Native Method)
	at com.facebook.react.uimanager.ViewManagersPropertyCache$PropSetter.updateViewProp(ViewManagersPropertyCache.java:83)
	... 21 more
Caused by: java.lang.IllegalArgumentException: Must not be null or empty
	at com.bumptech.glide.util.Preconditions.checkNotEmpty(Preconditions.java:39)
	at com.bumptech.glide.load.model.GlideUrl.<init>(GlideUrl.java:57)
	at com.dylanvann.fastimage.FastImageSource.getGlideUrl(FastImageSource.java:110)
	at com.dylanvann.fastimage.FastImageViewManager.setSrc(FastImageViewManager.java:75)
	... 23 more
java.lang.reflect.InvocationTargetException
	at java.lang.reflect.Method.invoke(Native Method)
	at com.facebook.react.uimanager.ViewManagersPropertyCache$PropSetter.updateViewProp(ViewManagersPropertyCache.java:83)
	at com.facebook.react.uimanager.ViewManagerPropertyUpdater$FallbackViewManagerSetter.setProperty(ViewManagerPropertyUpdater.java:131)
	at com.facebook.react.uimanager.ViewManagerPropertyUpdater.updateProps(ViewManagerPropertyUpdater.java:51)
	at com.facebook.react.uimanager.ViewManager.updateProperties(ViewManager.java:46)
	at com.facebook.react.uimanager.NativeViewHierarchyManager.createView(NativeViewHierarchyManager.java:268)
	at com.facebook.react.uimanager.UIViewOperationQueue$CreateViewOperation.execute(UIViewOperationQueue.java:198)
	at com.facebook.react.uimanager.UIViewOperationQueue$DispatchUIFrameCallback.dispatchPendingNonBatchedOperations(UIViewOperationQueue.java:1036)
	at com.facebook.react.uimanager.UIViewOperationQueue$DispatchUIFrameCallback.doFrameGuarded(UIViewOperationQueue.java:1007)
	at com.facebook.react.uimanager.GuardedFrameCallback.doFrame(GuardedFrameCallback.java:29)
	at com.facebook.react.modules.core.ReactChoreographer$ReactChoreographerDispatcher.doFrame(ReactChoreographer.java:172)
	at com.facebook.react.modules.core.ChoreographerCompat$FrameCallback$1.doFrame(ChoreographerCompat.java:84)
	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:984)
	at android.view.Choreographer.doCallbacks(Choreographer.java:798)
	at android.view.Choreographer.doFrame(Choreographer.java:727)
	at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:972)
	at android.os.Handler.handleCallback(Handler.java:790)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loop(Looper.java:192)
	at android.app.ActivityThread.main(ActivityThread.java:6906)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:550)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:828)
Caused by: java.lang.IllegalArgumentException: Must not be null or empty
	at com.bumptech.glide.util.Preconditions.checkNotEmpty(Preconditions.java:39)
	at com.bumptech.glide.load.model.GlideUrl.<init>(GlideUrl.java:57)
	at com.dylanvann.fastimage.FastImageSource.getGlideUrl(FastImageSource.java:110)
	at com.dylanvann.fastimage.FastImageViewManager.setSrc(FastImageViewManager.java:75)
	... 23 more
java.lang.IllegalArgumentException: Must not be null or empty
	at com.bumptech.glide.util.Preconditions.checkNotEmpty(Preconditions.java:39)
	at com.bumptech.glide.load.model.GlideUrl.<init>(GlideUrl.java:57)
	at com.dylanvann.fastimage.FastImageSource.getGlideUrl(FastImageSource.java:110)
	at com.dylanvann.fastimage.FastImageViewManager.setSrc(FastImageViewManager.java:75)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.facebook.react.uimanager.ViewManagersPropertyCache$PropSetter.updateViewProp(ViewManagersPropertyCache.java:83)
	at com.facebook.react.uimanager.ViewManagerPropertyUpdater$FallbackViewManagerSetter.setProperty(ViewManagerPropertyUpdater.java:131)
	at com.facebook.react.uimanager.ViewManagerPropertyUpdater.updateProps(ViewManagerPropertyUpdater.java:51)
	at com.facebook.react.uimanager.ViewManager.updateProperties(ViewManager.java:46)
	at com.facebook.react.uimanager.NativeViewHierarchyManager.createView(NativeViewHierarchyManager.java:268)
	at com.facebook.react.uimanager.UIViewOperationQueue$CreateViewOperation.execute(UIViewOperationQueue.java:198)
	at com.facebook.react.uimanager.UIViewOperationQueue$DispatchUIFrameCallback.dispatchPendingNonBatchedOperations(UIViewOperationQueue.java:1036)
	at com.facebook.react.uimanager.UIViewOperationQueue$DispatchUIFrameCallback.doFrameGuarded(UIViewOperationQueue.java:1007)
	at com.facebook.react.uimanager.GuardedFrameCallback.doFrame(GuardedFrameCallback.java:29)
	at com.facebook.react.modules.core.ReactChoreographer$ReactChoreographerDispatcher.doFrame(ReactChoreographer.java:172)
	at com.facebook.react.modules.core.ChoreographerCompat$FrameCallback$1.doFrame(ChoreographerCompat.java:84)
	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:984)
	at android.view.Choreographer.doCallbacks(Choreographer.java:798)
	at android.view.Choreographer.doFrame(Choreographer.java:727)
	at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:972)
	at android.os.Handler.handleCallback(Handler.java:790)
	at android.os.Handler.dispatchMessage(Handler.java:99)
	at android.os.Looper.loop(Looper.java:192)
	at android.app.ActivityThread.main(ActivityThread.java:6906)
	at java.lang.reflect.Method.invoke(Native Method)
	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:550)
	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:828)

解决方法

使用FastImage前,先验证uri,不是以 http/https 开头的,返回null。

const normalisedSource = source && typeof source.uri === 'string' && (source.uri.split('https://')[1] || source.uri.split('http://')[1]) ? source : null;
<FastImage source={normalisedSource} />
最后更新 2020-02-22
MIP.watch('startSearch', function (newVal, oldVal) { if(newVal) { var keyword = MIP.getData('keyword'); console.log(keyword); // 替换当前历史记录,新增 MIP.viewer.open('/s/' + keyword, {replace: true}); setTimeout(function () { MIP.setData({startSearch: false}) }, 1000); } }); MIP.watch('goHome', function (newVal, oldVal) { MIP.viewer.open('/', {replace: false}); });