内容简介:在ReactNative开发过程中,有时需要在原生端显示RN里的图片,这样的好处是可以通过热更新来更新APP里的图片,而不需要发布原生版本,而ReactNative里图片路径是相对路径,类似'./xxximage.png'的写法,原生端是无法解析这类路径,那么如果将RN的图片传递给原生端呢?resolveImage的打印结果如下:
在ReactNative开发过程中,有时需要在原生端显示RN里的图片,这样的好处是可以通过热更新来更新APP里的图片,而不需要发布原生版本,而ReactNative里图片路径是相对路径,类似'./xxximage.png'的写法,原生端是无法解析这类路径,那么如果将RN的图片传递给原生端呢?
解决方案
1、图片如果用网络图,那只需要将url字符串地址传递给原生即可,这种做法需要时间和网络环境加载图片,不属于本地图片,不是本方案所追求的最佳方式。
2、懒人做法是把RN的本地图片生成base64字符串然后传递给原生再解析,这种做法如果图片太大,字符串会相当长,同样不认为是最佳方案。
其实RN提供了相关的解决方法,如下:
resolveAssetSource()
Image.resolveAssetSource(source);复制代码
Resolves an asset reference into an object which has the properties uri
, width
, and height
.
resolveAssetSource 方法可以将资产引用解析为具有uri,width和height属性的对象。参数为一个数字(由require('。/ foo.png')返回的opaque类型)或 ImageSource。
示例代码如下:
const myImage = require('./Images/icon_splash.jpg'); const resolveAssetSource = require('react-native/Libraries/Image/resolveAssetSource'); const resolvedImage = resolveAssetSource(myImage); console.log(resolvedImage);复制代码
resolveImage的打印结果如下:
可以看到,resolveAssetSource 方法不仅返回了图片到宽高,还有Uri及scale属性值。 上图中,Uri的值为 http:// 开头的链接,这就涉及到RN对于Uri的定义规则:
(1)开发者模式下,图片会由Package Server 本地服务器加载,Uri会返http的本地链接。
(2)发布模式下,图片已经被打包到原生目录下,例如Android端res下的drawable资源目录。 所以我们可以在原生端通过Uri来获取rn中定义的图片资源。
Android端
/** * release模式下 uri为图片名称,例如, 在rn项目的Images目录下有张icon_splash名称的图片 * 那么 uri 为 images_icon_splash * 开发者模式下,图片格式为package server 地址,例如: http: // 192.xxx * @param params */ @ReactMethod public void showRNImage(ReadableMap params) { String rnImageUri; try { rnImageUri = params.getString("uri"); Log.i("showRNImage", "uri : " + rnImageUri); BitmapUtil.loadImage(rnImageUri); } catch (Exception e) { return; } }复制代码
loadImage方法接收Uri参数。来看loadImage方法是怎么实现的:
public static Drawable loadImage(String iconUri) { if (TextUtils.isEmpty(iconUri)) { return null; } Log.e("BitmapUtil", "isDebug: " + MainApplication.instance.isDebug()); if (MainApplication.instance.isDebug()) { return JsDevImageLoader.loadIcon(iconUri); } else { Uri uri = Uri.parse(iconUri); if (isLocalFile(uri)) { // 本地文件 return loadFile(uri); } else { return loadResource(iconUri); } } }复制代码
loadImage方法接收Uri参数。来看loadImage方法是怎么实现的:
public static Drawable loadImage(String iconUri) { if (TextUtils.isEmpty(iconUri)) { return null; } Log.e("BitmapUtil", "isDebug: " + MainApplication.instance.isDebug()); if (MainApplication.instance.isDebug()) { return JsDevImageLoader.loadIcon(iconUri); } else { Uri uri = Uri.parse(iconUri); if (isLocalFile(uri)) { // 本地文件 return loadFile(uri); } else { return loadResource(iconUri); } } }复制代码
首先我们判断是否是开发者模式,如果是则执行loadIcon方法,从本地目录直接加载。否则执行从手机本地目录加载或者根据资源ID加载。
开发模式下,Uri 为链接模式,所以我们可以通过流来获取
@NonNull private static Drawable tryLoadIcon(String iconDevUri) throws IOException { URL url = new URL(iconDevUri); Bitmap bitmap = BitmapFactory.decodeStream(url.openStream()); BitmapDrawable bitmapDrawable = new BitmapDrawable(MainApplication.instance.getResources(), bitmap); Log.e("JsDevImageLoader", "bitmap drawable width:" + bitmapDrawable.getIntrinsicWidth()); return bitmapDrawable; }复制代码
发布模式为以下两种方式:
/** * 加载手机本地目录图片 * @param uri * @return */ private static Drawable loadFile(Uri uri) { Bitmap bitmap = BitmapFactory.decodeFile(uri.getPath()); return new BitmapDrawable(MainApplication.instance.getResources(), bitmap); } /** * 加载drawable目录下的图片 * @param iconUri * @return */ private static Drawable loadResource(String iconUri) { return ResourceDrawableIdHelper .instance .getResourceDrawable(MainApplication.instance, iconUri); }复制代码
iOS端
iOS端相对Android简单很多,只需要直接解析成UIImage即可:
#import <React/RCTConvert.h> RCT_EXPORT_METHOD(showRNImage:(id)rnImageData){ dispatch_async(dispatch_get_main_queue(), ^{ UIImage *rnImage = [RCTConvert UIImage:rnImageData]; ... }); }复制代码
总结
在原生端读取RN图片,不管是混合开发,还是纯RN开发,涉及的使用场景都是很多的。例如,动态更新Splash。所以掌握了这个技能,有助于我们做出体验更好的应用。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。