React Native Image组件源码笔记

前言

以前在做项目的时候遇到一个问题:如何将rn的图片传给原生使用?
以前总是百度,但百度遍也没有找到一篇博客给出答案,又去各种技术交流群问,也没有人理我,于是GG。(百度查不到等于我不知道,不知道多少人和我一样。。。)
近日,不知脑子开了什么光突然想到一个问题,rn的image是如何实现的。我是不是可以借鉴一下?于是便有了这篇笔记。(ios不太懂,只写了android)

1.rn端

打开项目找到node-modules目录下的react-native,再找到image目录。可以看到image目录下有个image.android.js文件。点进入:
React Native Image组件源码笔记_第1张图片

进入到image.android.js后发现:原来rn的image也是封装的原生组件。(有兴趣自己点进去看,我就直接截图重点了。)这两行如果看不懂,附送rn中文网地址https://reactnative.cn/docs/0.51/native-component-android.html#content(怎么感觉江青青技术专栏和中文网的文档有点像啊。。。)
React Native Image组件源码笔记_第2张图片

2.android端

现在就要找rn的android代码了,再去翻node-modules。发现了ReactAndroid这个目录,用ide的全局查找搜索RCTImageView。然后发现,果然是在这里。(webStorm关于java代码不能Ctrl进去,我就将整个ReactAndroid抠出来放在Android studio中,方便阅读。)
React Native Image组件源码笔记_第3张图片
找重点,我们发现rn其实是将src传入ReactImageView中,那就再看看他的ReactImageView是怎么写的。
React Native Image组件源码笔记_第4张图片
这里我们发现他其实是将rn传过来的src传到ImageSource中处理了一下,再添加到mSources集合中。
React Native Image组件源码笔记_第5张图片
这里段代码的功能就是将rn传过来的图片显示在界面上。
React Native Image组件源码笔记_第6张图片

写个demo验证下

看了image的源码后我们大概了解了rn是如何将js端的图片路径传给android的逻辑。
现在我们取关键部分的代码贴出来。

 @ReactProp(name = "setSource")
    public void setSource(FrescoView view,ReadableArray sources){
        List  mSources = new LinkedList<>();
        ReadableMap source = sources.getMap(0);
        String uri = source.getString("uri");
        ImageSource imageSource = new ImageSource(mReactContext, uri);
        ResizeOptions resizeOptions = new ResizeOptions(100, 100);
        ImageRequestBuilder imageRequestBuilder = ImageRequestBuilder.newBuilderWithSource(imageSource.getUri())
                .setPostprocessor(new RoundedCornerPostprocessor())
                .setResizeOptions(resizeOptions)
                .setAutoRotateEnabled(true)
                .setProgressiveRenderingEnabled(true);

        ImageRequest imageRequest = ReactNetworkImageRequest.fromBuilderWithHeaders(imageRequestBuilder,null );
        AbstractDraweeControllerBuilder mDraweeControllerBuilder = Fresco.newDraweeControllerBuilder();
        mDraweeControllerBuilder
                .setAutoPlayAnimations(true)
                .setCallerContext(mCallerContext)
               // .setOldController(getController())
                .setImageRequest(imageRequest)
                .build();
        mDraweeControllerBuilder.reset();
    }

RoundedCornerPostprocessor类。

 private class RoundedCornerPostprocessor extends BasePostprocessor {

        void getRadii(Bitmap source, float[] computedCornerRadii, float[] mappedRadii) {
            mScaleType.getTransform(
                    sMatrix,
                    new Rect(0, 0, source.getWidth(), source.getHeight()),
                    source.getWidth(),
                    source.getHeight(),
                    0.0f,
                    0.0f);
            sMatrix.invert(sInverse);

            mappedRadii[0] = sInverse.mapRadius(computedCornerRadii[0]);
            mappedRadii[1] = mappedRadii[0];

            mappedRadii[2] = sInverse.mapRadius(computedCornerRadii[1]);
            mappedRadii[3] = mappedRadii[2];

            mappedRadii[4] = sInverse.mapRadius(computedCornerRadii[2]);
            mappedRadii[5] = mappedRadii[4];

            mappedRadii[6] = sInverse.mapRadius(computedCornerRadii[3]);
            mappedRadii[7] = mappedRadii[6];
        }

        @Override
        public void process(Bitmap output, Bitmap source) {
            //cornerRadii(sComputedCornerRadii);

            output.setHasAlpha(true);
            if (FloatUtil.floatsEqual(sComputedCornerRadii[0], 0f) &&
                    FloatUtil.floatsEqual(sComputedCornerRadii[1], 0f) &&
                    FloatUtil.floatsEqual(sComputedCornerRadii[2], 0f) &&
                    FloatUtil.floatsEqual(sComputedCornerRadii[3], 0f)) {
                super.process(output, source);
                return;
            }
            Paint paint = new Paint();
            paint.setAntiAlias(true);
            paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
            Canvas canvas = new Canvas(output);

            float[] radii = new float[8];

            getRadii(source, sComputedCornerRadii, radii);

            Path pathForBorderRadius = new Path();

            pathForBorderRadius.addRoundRect(
                    new RectF(0, 0, source.getWidth(), source.getHeight()),
                    radii,
                    Path.Direction.CW);

            canvas.drawPath(pathForBorderRadius, paint);
        }

    }

ImageSource类


/**
 * Class describing an image source (network URI or resource) and size.
 */
public class ImageSource {

    private @Nullable Uri mUri;
    private String mSource;
    private double mSize;
    private boolean isResource;

    public ImageSource(Context context, String source, double width, double height) {
        mSource = source;
        mSize = width * height;

        // Important: we compute the URI here so that we don't need to hold a reference to the context,
        // potentially causing leaks.
        mUri = computeUri(context);
    }

    public ImageSource(Context context, String source) {
        this(context, source, 0.0d, 0.0d);
    }

    /**
     * Get the source of this image, as it was passed to the constructor.
     */
    public String getSource() {
        return mSource;
    }

    /**
     * Get the URI for this image - can be either a parsed network URI or a resource URI.
     */
    public Uri getUri() {
        return Assertions.assertNotNull(mUri);
    }

    /**
     * Get the area of this image.
     */
    public double getSize() {
        return mSize;
    }

    /**
     * Get whether this image source represents an Android resource or a network URI.
     */
    public boolean isResource() {
        return isResource;
    }

    private Uri computeUri(Context context) {
        try {
            Uri uri = Uri.parse(mSource);
            // Verify scheme is set, so that relative uri (used by static resources) are not handled.
            return uri.getScheme() == null ? computeLocalUri(context) : uri;
        } catch (Exception e) {
            return computeLocalUri(context);
        }
    }

    private Uri computeLocalUri(Context context) {
        isResource = true;
        return ResourceDrawableIdHelper.getInstance().getResourceDrawableUri(context, mSource);
    }
}

rn的代码
React Native Image组件源码笔记_第7张图片
使用
React Native Image组件源码笔记_第8张图片
效果,(偷个懒,直接写在项目里了)
React Native Image组件源码笔记_第9张图片

你可能感兴趣的:(学习笔记)