React Native for Android 熱部署圖片本身定義方案

情景

熱部署時,咱們指望升級包中包括js代碼與圖片資源。javascript

bundle的熱部署網上已經有兩種方案了,一種是用反射,一種是利用RN自帶函數。將bundle初始化時直接放到指定文件夾下,以後經過替換bundle文件實現代碼熱部署。java

咱們但願圖片也可以實現熱部署,如下是一個比較簡單的解決方式。react

詳細需求:client解析從server下發的壓縮包(zip),當中含js源文件index.android.bundle 和 圖片包,解壓後ReactNative指向 解壓後index.android.bundle中的js代碼,js代碼中使用的圖片資源指向android

            解壓後的圖片資源。(data/data/files/或sdcard裏)算法

       


           

           

           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.爲了讓二者在代碼形式上一致post

需要本身定義協議:http-cage://xxx/xxx.png 相似這樣的形式,在不一樣環境下獲取不一樣路徑的圖片。ui

 

Image載入資源機制

涉及類:

js: RCTImage.js, AssetRegistry.js,resolveAssetSource.js,Image.android.js,AssetRegistry.js

Native:ReactImageView.java

 

調用順序關係:


 

1:遍歷檢測使用外部資源(比方RNserver上的圖片)。檢測到一處調用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 (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 = 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

相關文章
相關標籤/搜索