React Native for Android 热部署图片自定义方案
情景热部署时,我们期望升级包中包含js代码与图片资源。bundle的热部署网上已经有两种方案了,一种是用反射,一种是利用RN自带函数,将bundle初始化时直接放到指定目录下,之后通过替换bundle文件实现代码热部署。我们希望图片也可以实现热部署,下面是一个比较简单的解决方案。 具体需求:客户端解析从服务器下发的压缩包(zip),其中含js源文件index.android.bundle 和 图片包,解压后ReactNative指向 解压后index.android.bundle中的js代码,js代码中使用的图片资源指向 解压后的图片资源。(data/data/files/或sdcard里)
客户端根据运行场景 debug or release 决定从服务器 或者 本地解压目录获取图片资源,也就是一个url兼容在不同场景下访问不同资源。 Image 使用示例
上面两种都会发送网络请求 期望:本地开发时,图片来自1,上线后,图片来自4.为了让两者在代码形式上一致 需要自定义协议:http-cage://xxx/xxx.png类似这种形式,在不同环境下获取不同路径的图片。
Image加载资源机制涉及类: js: RCTImage.js,AssetRegistry.js,resolveAssetSource.js,Image.android.js,AssetRegistry.js Native:ReactImageView.java
调用顺序关系:
1:遍历检测使用外部资源(比如RN服务器上的图片),检测到一处调用AssetRegistry 2:AssetRegistry.registerAsset 将资源加入到AssetRegistry的assets数组中,将id返回,也就是资源在assets中的索引值。
3 检测到<Image 标签 触发 Image.android.js render 4:resolveAssetSource.resolveAssetSource(source) source可能是object类型,封装了图片url,或者是number类型,也就是资源id,id值由 步骤2 决定。
5: 判断资源类型 object:非本地资源(网络、sdcard、apk中图片)跳6
number: 资源id (RN服务器) 跳7 6: return object 跳10 7: 根据id从AssetRegistry的assets中取出资源asset。
var asset = AssetRegistry.getAssetByID(source); 8:拼接资源路径 1.获取RN服务器地址
var devServerURL = getDevServerURL(); //获取RN 服务器地址, 一般是 http://localhost:8081/ 2.取到服务器地址,根据地址与asset中的路径拼接,"http://localhost:8081/assets/image/open.png?platform=android&hash=ff54b39af9b07e7380a4eda7e0212643" 3.取不到服务器地址,从压缩包中获得地址getPathInArchive。 地址返回。9 9: 根据url 构建和 6类似的object
function assetToImageSource(asset): ResolvedAssetSource { var devServerURL = getDevServerURL(); return { __packager_asset: true,width: asset.width,height: asset.height,uri: devServerURL ? getPathOnDevserver(devServerURL,asset) : getPathInArchive(asset),scale: pickScale(asset.scales,PixelRatio.get()),}; } 10:Image.android.js 收到 object,与 NativeProps合并,
var nativeProps = merge(this.props,{ style,src: source.uri,}); 11:合并后的NativeProps传入 RCTImage 12: RCTImage解析NativeProps将uri传给java的ReactImageView.java setSource
协议自定义方案在11到12之间进行协议判断,修改Image.android.js文件及resolveAssetSource.js。
Image.android.js render: function() { ... var prefix = 'http-cage://'; var match = nativeProps.src.indexOf(prefix); if(match == 0){//以http-cage://开头 console.log(__DEV__); var realUrl = nativeProps.src.substring(prefix.length,nativeProps.src.length); if(debug){//debug 情况 RN 服务器:http://10.0.3.5:8081/assets/image/help.png nativeProps.src = resolveAssetSource.getDevServerURL()+realUrl; }else {//release 情况 图片路径:file:///sdcard/image/help.png nativeProps.src = 'file://'+'/sdcard/'+realUrl; } } } resolveAssetSource.js //使 getDevServerURL 外部可用 module.exports.getDevServerURL = getDevServerURL; 自定义协议使用示例
0.14开始图片放到 根目录 img文件下并且在js中被require,
<Image source={require('./img/help.png')} style={styles.helpImage}/> 后记 经同事验证,img文件夹下的图片被打到了apk的res中去,之前误导大家了,sorry (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |