原生端(iOS和Android)读取ReactNative本地图片

栏目: IOS · Android · 发布时间: 4年前

内容简介:在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的打印结果如下:

原生端(iOS和Android)读取ReactNative本地图片

可以看到,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。所以掌握了这个技能,有助于我们做出体验更好的应用。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

High Performance Python

High Performance Python

Micha Gorelick、Ian Ozsvald / O'Reilly Media / 2014-9-10 / USD 39.99

If you're an experienced Python programmer, High Performance Python will guide you through the various routes of code optimization. You'll learn how to use smarter algorithms and leverage peripheral t......一起来看看 《High Performance Python》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具