应用想做成动态加载图片机制,由于我们的图片资源内置到assets目录下,当RN模块有图片升级后,会放在应用内文件系统的升级文件夹下。加载图片的策略为优先加载升级目录下,然后再加载Assets目录下。
几种方案,这里探讨一下:
方案一:只更改Java原生模块,这里我们可以在MainReactPackage.java里看到,ReactNative对原生Android的ImageView的封装类之后的管理类有三个,当然都是可扩展的~ 这几个分别的:
RCTImageViewManager.java
FrescoBaseReactTextInlineImageViewManager.java
ReactImageManager.java
这三个类分别对应Fresco及ReactNative的图片处理类。比如ReactImageView对应ReactImageManager,在这个类的setSource方法中我们JS传递过来的uri进行处理,自定义设置我们希望显示的图片加载是在 File系统目录或是Assets目录。
这种方案的劣热在于要改好几个RN的图片封装图,而且还是原生类,不爽~
方案二:在resolveAssetSource.js中的resolveAssetSource(source: any)方法中动态更新显示图片的位置,当然需要先封装一个同步调用原生的java方法。用以判断File系统文件或Assets目录下是否有希望显示的图片。
劣势:需要提供一个Java的同步方法,及修改ReactNative源码。。怎样使用ReactNative调用Java的方法同步返回数据,讲参考之前的博文。
方案三:在JS应用层,在页面中直接调用Java的同步方法,判断File系统目录或Assets文件中的图片资源。然后直接设置Image控件的source属性。
劣势:也需要提供一个Java同步方法,但不需要更改ReactNative的源码。拼装asset:/目录时需要根据resolveAssetSource里生成图片的文件名规则。即文件路径+文件名,中间用下划线,大概是这样子~
方案四:在加载Bundle后运行runApplication之后,通过启动监听消息把File目录或Assets目录下的图片资源列表存入ReactNative环境中,然后在渲染Image的时候读这个内存中的数据进行匹配即可。
在我们应用中做了一个关于效率的尝试,仅供于参考。
如果是在ReactImageView.setSource方法中,
1)每次显示一个图片前都进行一次查看升级目录下此图片资源是否存在,假设每次页面包含的页面数与所用耗时:
10张图片--------->0~2ms
100张图片-------->3~15ms
1000张图片------>52~94ms
通过for循环模拟,耗时浮动范围都比较均匀。
2)首次显示时把升级目录下的文件列表存储在一个ArrayList中,后续每次读取都从ArrayList是判断是否存在。
首次全部文件列表读取,然后存入ArrayList所耗时45ms。
100张图片----------> 1~8ms(90%在耗时为3ms内)
1000张图片--------->1-61ms(80%所耗时在10ms内)
是在开发模式下进行的,手机为一加3T,两年前的旗舰机。
注:调用同步接口并且再判断文件是否存在、维护list需要考滤性能!!!!!几种方案都试过了是可行的,不知你喜欢哪一种!
如果喜欢,请默默关注,不断更新 ReactNative原创有见解的博文~