React Native for Android 热部署图片自己定义方案

人生必须的知识就是引人向光明方面的明灯。这篇文章主要讲述React Native for Android 热部署图片自己定义方案相关的知识,希望能为你提供帮助。
情景热部署时,我们期望升级包中包括js代码与图片资源。
bundle的热部署网上已经有两种方案了,一种是用反射,一种是利用RN自带函数。将bundle初始化时直接放到指定文件夹下,之后通过替换bundle文件实现代码热部署。
我们希望图片也能够实现热部署,以下是一个比較简单的解决方式。
详细需求:client解析从server下发的压缩包(zip),当中含js源文件index.android.bundle 和 图片包,解压后ReactNative指向 解压后index.android.bundle中的js代码,js代码中使用的图片资源指向
            解压后的图片资源。(data/data/files/或sdcard里)
       

React Native for Android 热部署图片自己定义方案

文章图片



           
           
            client依据执行场景 debug or release 决定从server 或者   本地解压文件夹获取图片资源,也就是一个url兼容在不同场景下訪问不同资源。
            Image 使用演示样例
//1.请求react native server的图片 < Image source={require(' ./image/help.png' )} style={styles.helpImage}/> //2.请求网络的图片 < Image source={uri:' http://xxxxxx/image/help.png' } style={styles.helpImage}/> //3.请求native图片 < Image source={{uri:' help' }} style={styles.helpImage}/> //4.请求手机指定路径图片 < Image source={{uri:' file:///sdcard/help.png' }}


上面两种都会发送网络请求
期望:本地开发时,图片来自1,上线后,图片来自4.为了让两者在代码形式上一致
须要自己定义协议:http-cage://xxx/xxx.png  类似 这样的形式,在不同环境下获取不同路径的图片。

 
Image载入资源机制涉及类:
js: RCTImage.js, AssetRegistry.js,resolveAssetSource.js,Image.android.js,AssetRegistry.js
Native:ReactImageView.java
 
调用顺序关系:
React Native for Android 热部署图片自己定义方案

文章图片


 
1:遍历检測使用外部资源(比方RNserver上的图片)。检測到一处调用AssetRegistry
2:AssetRegistry.registerAsset
    将资源增加到AssetRegistry的assets数组中,将id返回,也就是资源在assets中的索引值 。
React Native for Android 热部署图片自己定义方案

文章图片


 
3 检測到< Image 标签 触发 Image.android.js   render
4:resolveAssetSource.resolveAssetSource(source)
  source可能是object类型,封装了图片url。或者是number类型。也就是资源id,id值 由 步骤2 决定。 
   
5: 推断资源类型
    object:非本地资源(网络、sdcard、apk中图片)跳6
     
React Native for Android 热部署图片自己定义方案

文章图片



    number: 资源id (RNserver) 跳7
6: return object   跳10
7: 依据id从AssetRegistry的assets中取出资源asset。


var asset = AssetRegistry.getAssetByID(source);



8:拼接资源路径   
  1.获取RNserver地址

var devServerURL = getDevServerURL(); //获取RN server地址。 通常是 http://localhost:8081/


    2.取到server地址,依据地址与asset中的路径拼接," http://localhost:8081/assets/image/open.png?
platform=android& hash=ff54b39af9b07e7380a4eda7e0212643"
    3.取不到server地址,从压缩包中获得地址  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 server:http://10.0.3.5:8081/assets/image/help.png nativeProps.src = https://www.songbingjia.com/android/resolveAssetSource.getDevServerURL()+realUrl; }else {//release 情况 图片路径:file:///sdcard/image/help.png nativeProps.src = ' file://' +' /sdcard/' +realUrl; } } }



 
resolveAssetSource.js //使 getDevServerURL 外部可用 module.exports.getDevServerURL = getDevServerURL;


自己定义协议使用演示样例
//測试版本号0.13.2
< Image source={{uri: ‘http-cage://image/finance.png‘}} style={styles.phoneImage}/>






0.14開始图片放到 根文件夹 img文件下而且在js中被require,就会被打入bundle中。压缩比非常夸张,不知道用了什么压缩算法。


< Image source={require(' ./img/help.png' )} style={styles.helpImage}/>

后记
经同事验证,img目录下的图片被打到了apk的res中去,之前误导大家了,sorry


【React Native for Android 热部署图片自己定义方案】

















    推荐阅读