GVKun编程网logo

如何设计一个好用的 React Image 组件?(react组件设计原则)

26

本文的目的是介绍如何设计一个好用的ReactImage组件?的详细情况,特别关注react组件设计原则的相关信息。我们将通过专业的研究、有关数据的分析等多种方式,为您呈现一个全面的了解如何设计一个好用

本文的目的是介绍如何设计一个好用的 React Image 组件?的详细情况,特别关注react组件设计原则的相关信息。我们将通过专业的研究、有关数据的分析等多种方式,为您呈现一个全面的了解如何设计一个好用的 React Image 组件?的机会,同时也不会遗漏关于Android 设计一个菱形形状的Imageview组件.、com.facebook.imagepipeline.image.CloseableAnimatedImage的实例源码、com.facebook.react.views.image.ImageResizeMode的实例源码、com.facebook.react.views.image.ReactImageManager的实例源码的知识。

本文目录一览:

如何设计一个好用的 React Image 组件?(react组件设计原则)

如何设计一个好用的 React Image 组件?(react组件设计原则)

前言

本文为笔者阅读 react-image[1] 源码过程中的总结,若有所错漏烦请指出。✨ 仓库传送门[2]

https://github.com/worldzhao/blog/issues/1

<img />可以说是开发过程中极其常用的标签了。但是很多同学都是<img src="xxx.png" />一把梭,直到 UI 小姐姐来找你谈谈人生理想:

  1. 图片加载太慢,需要展示 loading占位符;
  2. 图片加载失败,加载备选图片或展示 error占位符。

作为开发者的我们,可能会经历以下几个阶段:

  • 第一阶段: img标签上使用 onLoad以及 onError进行处理;
  • 第二阶段:写一个较为通用的组件;
  • 第三阶段:抽离 hooks,使用方自定义视图组件(当然也要提供基本组件);

现在让我们直接从第三阶段开始,看看如何使用少量代码打造一个易用性、封装性以及扩展性俱佳的image组件。

preview.gif

useImage

首先分析可复用的逻辑,可以发现使用者需要关注三个状态:loadingerror以及src,毕竟加载图片也是异步请求嘛。

react-use[3] 熟悉的同学会很容易联想到useAsync

自定义一个 hooks,接收图片链接作为参数,返回调用方需要的三个状态。

基础实现

import * as React from "react";

// 将图片加载转为promise调用形式
function imgPromise(src: string{
  return new Promise((resolve, reject) => {
    const i = new Image();
    i.onload = () => resolve();
    i.onerror = reject;
    i.src = src;
  });
}

function useImage({ src }: { src: string }): {
  src: string | undefined,
  isLoading: boolean,
  error: any,
} {
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(null);
  const [value, setValue] = (React.useState < string) | (undefined > undefined);

  React.useEffect(() => {
    imgPromise(src)
      .then(() => {
        // 加载成功
        setLoading(false);
        setValue(src);
      })
      .catch((error) => {
        // 加载失败
        setLoading(false);
        setError(error);
      });
  }, [src]);

  return { isLoading: loading, src: value, error: error };
}

我们已经完成了最基础的实现,现在来慢慢优化。

性能优化

对于同一张图片来讲,在组件 A 加载过的图片,组件 B 不用再走一遍new Image()的流程,直接返回上一次结果即可。

+ const cache: {
+  [key: string]: Promise<void>;
+ } = {};

function useImage({
  src,
}: {
  src: string;
}): { src: string | undefined; isLoading: boolean; error: any } {
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(null);
  const [value, setValue] = React.useState<string | undefined>(undefined);

  React.useEffect(() => {
+   if (!cache[src]) {
+     cache[src] = imgPromise(src);
+   }

-   imgPromise(src)
+   cache[src]
      .then(() => {
        setLoading(false);
        setValue(src);
      })
      .catch(error => {
        setLoading(false);
        setError(error);
      });
  }, [src]);

  return { isLoading: loading, src: value, error: error };
}

优化了一丢丢性能。

支持 srcList

上文提到过一点:图片加载失败,加载备选图片或展示error占位符。

展示error占位符我们可以通过error状态去控制,但是加载备选图片的功能还没有完成。

主要思路如下:

  1. 将入参 src改为 srcList,值为图片 url或图片(含备选图片)的 url数组;
  2. 从第一张开始加载,若失败则加载第二张,直到某一张成功或全部失败,流程结束。类似于 tapable [4]AsyncSeriesBailHook

对入参进行处理:

const removeBlankArrayElements = (a: string[]) => a.filter((x) => x);

const stringToArray = (x: string | string[]) => (Array.isArray(x) ? x : [x]);

function useImage({ srcList }: { srcList: string | string[] }): {
  src: string | undefined,
  loading: boolean,
  error: any,
} {
  // 获取url数组
  const sourceList = removeBlankArrayElements(stringToArray(srcList));
  // 获取用于缓存的键名
  const sourceKey = sourceList.join("");
}

接下来就是重要的加载流程啦,定义promiseFind方法,用于完成以上加载图片的逻辑。

/**
 * 注意 此处将imgPromise作为参数传入,而没有直接使用imgPromise
 * 主要是为了扩展性
 * 后面会将imgPromise方法作为一个参数由使用者传入,使得使用者加载图片的操作空间更大
 * 当然若使用者不传该参数,就是用默认的imgPromise方法
 */

function promiseFind(
  sourceList: string[],
  imgPromise: (src: string
) => Promise<void>
): Promise<string
{
  let done = false;
  // 重新使用Promise包一层
  return new Promise((resolve, reject) => {
    const queueNext = (src: string) => {
      return imgPromise(src).then(() => {
        done = true;
        // 加载成功 resolve
        resolve(src);
      });
    };

    const firstPromise = queueNext(sourceList.shift() || "");

    // 生成一条promise链[队列],每一个promise都跟着catch方法处理当前promise的失败
    // 从而继续下一个promise的处理
    sourceList
      .reduce((p, src) => {
        // 如果加载失败 继续加载
        return p.catch(() => {
          if (!done) return queueNext(src);
          return;
        });
      }, firstPromise)
      // 全都挂了 reject
      .catch(reject);
  });
}

再来改动useImage

const cache: {
-  [key: string]: Promise<void>;
+  [key: string]: Promise<string>;
} = {};

function useImage({
-  src,
+  srcList,
}: {
- src: string;
+ srcList: string | string[];
}): { src: string | undefined; loading: boolean; error: any } {
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(null);
  const [value, setValue] = React.useState<string | undefined>(undefined);

// 图片链接数组
+ const sourceList = removeBlankArrayElements(stringToArray(srcList));
// cache唯一键名
+ const sourceKey = sourceList.join('''');

  React.useEffect(() => {
-   if (!cache[src]) {
-     cache[src] = imgPromise(src);
-   }

+   if (!cache[sourceKey]) {
+     cache[sourceKey] = promiseFind(sourceList, imgPromise);
+   }

-    cache[src]
-    .then(() => {
+    cache[sourceKey]
+     .then((src) => {
        setLoading(false);
        setValue(src);
      })
      .catch(error => {
        setLoading(false);
        setError(error);
      });
  }, [src]);

  return { isLoading: loading, src: value, error: error };
}

需要注意的一点:现在传入的图片链接可能不是单个src,最终设置的valuepromiseFind找到的src,所以 cache 类型定义也有变化。

react-image-1

自定义 imgPromise

前面提到过,加载图片过程中,使用方可能会插入自己的逻辑,所以将 imgPromise 方法作为可选参数loadImg传入,若使用者想自定义加载方法,可传入该参数。

function useImage({
+ loadImg = imgPromise,
  srcList,
}: {
+ loadImg?: (src: string) => Promise<void>;
  srcList: string | string[];
}): { src: string | undefined; loading: boolean; error: any } {
  const [loading, setLoading] = React.useState(true);
  const [error, setError] = React.useState(null);
  const [value, setValue] = React.useState<string | undefined>(undefined);

  const sourceList = removeBlankArrayElements(stringToArray(srcList));
  const sourceKey = sourceList.join('''');

  React.useEffect(() => {
    if (!cache[sourceKey]) {
-     cache[sourceKey] = promiseFind(sourceList, imgPromise);
+     cache[sourceKey] = promiseFind(sourceList, loadImg);
    }

    cache[sourceKey]
      .then(src => {
        setLoading(false);
        setValue(src);
      })
      .catch(error => {
        setLoading(false);
        setError(error);
      });
  }, [sourceKey]);

  return { loading: loading, src: value, error: error };
}

实现 Img 组件

完成useImage后,我们就可以基于其实现 Img 组件了。

预先定义好相关 API:

属性 说明 类型 默认值 src 图片链接 string / string[] - loader 可选,加载过程占位元素 ReactNode null unloader 可选,加载失败占位元素 ReactNode null loadImg 可选,图片加载方法,返回一个 Promise (src:string)=>Promise imgPromise 当然,除了以上 API,还有<img />标签原生属性。编写类型声明文件如下:

export type ImgProps = Omit<
  React.DetailedHTMLProps<
    React.ImgHTMLAttributes<HTMLImageElement>,
    HTMLImageElement
  >,
  "src"
> &
  Omit<useImageParams, "srcList"> & {
    src: useImageParams["srcList"];
    loader?: JSX.Element | null;
    unloader?: JSX.Element | null;
  };

实现如下:

export default ({
  src: srcList,
  loadImg,
  loader = null,
  unloader = null,
  ...imgProps
}: ImgProps) => {
  const { src, loading, error } = useImage({
    srcList,
    loadImg,
  });

  if (src) return <img src={src} {...imgProps} />;
  if (loading) return loader;
  if (error) return unloader;

  return null;
};

测试效果如下:

react-image-2

结语

值得注意的是,本文遵循 react-image 大体思路,但部分内容暂未实现(所以代码可读性要好一点)。其它特性,如:

  1. 支持 Suspense 形式调用;
  2. 默认在渲染图片前会进行 decode,避免页面卡顿或者闪烁。

有兴趣的同学可以看看下面这些文章:

  • 用于数据获取的 Suspense(试验阶段) [5]
  • 错误边界(Error Boundaries) [6]
  • React:Suspense 的实现与探讨 [7]
  • HTMLImageElement.decode() [8]
  • Chrome 图片解码与 Image.decode API [9]

参考资料

[1]

react-image: https://github.com/mbrevda/react-image

[2]

✨ 仓库传送门: https://github.com/worldzhao/build-your-own-react-image

[3]

react-use: https://github.com/streamich/react-use

[4]

tapable: https://github.com/webpack/tapable

[5]

用于数据获取的 Suspense(试验阶段): https://zh-hans.reactjs.org/docs/concurrent-mode-suspense.html

[6]

错误边界(Error Boundaries): https://zh-hans.reactjs.org/docs/error-boundaries.html#introducing-error-boundaries

[7]

React:Suspense 的实现与探讨: https://zhuanlan.zhihu.com/p/34210780

[8]

HTMLImageElement.decode(): https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLImageElement/decode

[9]

Chrome 图片解码与 Image.decode API: https://zhuanlan.zhihu.com/p/43991630


本文分享自微信公众号 - 前端从进阶到入院(code_with_love)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

Android 设计一个菱形形状的Imageview组件.

Android 设计一个菱形形状的Imageview组件.

网上没有资料,特来请教下大神


Android 设计一个菱形形状的Imageview组件. >> android

这个答案描述的挺清楚的:
http://www.goodpm.net/postreply/android/1010000007107851/Android设计一个菱形形状的Imageview组件.html

com.facebook.imagepipeline.image.CloseableAnimatedImage的实例源码

com.facebook.imagepipeline.image.CloseableAnimatedImage的实例源码

项目:GitHub    文件:BoxingFrescoLoader.java   
private Drawable createDrawableFromFetchedResult(Context context,CloseableImage image) {
    if (image instanceof CloseableStaticBitmap) {
        CloseableStaticBitmap closeableStaticBitmap = (CloseableStaticBitmap) image;
        BitmapDrawable bitmapDrawable = createBitmapDrawable(context,closeableStaticBitmap.getUnderlyingBitmap());
        return (closeableStaticBitmap.getRotationAngle() != 0 && closeableStaticBitmap.getRotationAngle() != -1 ? new OrientedDrawable(bitmapDrawable,closeableStaticBitmap.getRotationAngle()) : bitmapDrawable);
    } else if (image instanceof CloseableAnimatedImage) {
        AnimatedDrawableFactory animatedDrawableFactory = Fresco.getimagePipelineFactory().getAnimatedFactory().getAnimatedDrawableFactory(context);
        if (animatedDrawableFactory != null) {
            AnimatedDrawable animatedDrawable = (AnimatedDrawable) animatedDrawableFactory.create(image);
            if (animatedDrawable != null) {
                return animatedDrawable;
            }
        }
    }
    throw new UnsupportedOperationException("Unrecognized image class: " + image);
}
项目:GitHub    文件:AnimatedSingleUsePostprocessorProducerTest.java   
@Test
public void testNonStaticBitmapIsPassedOn() {
  SingleUsePostprocessorConsumer postprocessorConsumer = produceResults();
  CloseableAnimatedImage sourceCloseableAnimatedImage = mock(CloseableAnimatedImage.class);
  CloseableReference<CloseableImage> sourceCloseableImageRef =
      CloseableReference.<CloseableImage>of(sourceCloseableAnimatedImage);
  postprocessorConsumer.onNewResult(sourceCloseableImageRef,Consumer.IS_LAST);
  sourceCloseableImageRef.close();
  mTestExecutorService.runUntilIdle();

  mInorder.verify(mConsumer).onNewResult(any(CloseableReference.class),eq(Consumer.IS_LAST));
  mInorder.verifyNoMoreInteractions();

  assertEquals(1,mResults.size());
  CloseableReference<CloseableImage> res0 = mResults.get(0);
  assertTrue(CloseableReference.isValid(res0));
  assertSame(sourceCloseableAnimatedImage,res0.get());
  res0.close();

  verify(sourceCloseableAnimatedImage).close();
}
项目:GitHub    文件:AnimatedRepeatedPostprocessorProducerTest.java   
@Test
public void testNonStaticBitmapIsPassedOn() {
  RepeatedPostprocessorConsumer postprocessorConsumer = produceResults();
  RepeatedPostprocessorRunner repeatedPostprocessorRunner = getRunner();

  CloseableAnimatedImage sourceCloseableAnimatedImage = mock(CloseableAnimatedImage.class);
  CloseableReference<CloseableImage> sourceCloseableImageRef =
      CloseableReference.<CloseableImage>of(sourceCloseableAnimatedImage);
  postprocessorConsumer.onNewResult(sourceCloseableImageRef,eq(Consumer.NO_FLAGS));
  mInorder.verifyNoMoreInteractions();

  assertEquals(1,res0.get());
  res0.close();

  performCancelAndVerifyOnCancellation();
  verify(sourceCloseableAnimatedImage).close();
}
项目:Boxing    文件:BoxingFrescoLoader.java   
private Drawable createDrawableFromFetchedResult(Context context,closeableStaticBitmap.getRotationAngle()) : bitmapDrawable);
    } else if (image instanceof CloseableAnimatedImage) {
        AnimatedDrawableFactory animatedDrawableFactory = Fresco.getimagePipelineFactory().getAnimatedFactory().getAnimatedDrawableFactory(context);
        if (animatedDrawableFactory != null) {
            AnimatedDrawable animatedDrawable = (AnimatedDrawable) animatedDrawableFactory.create(image);
            if (animatedDrawable != null) {
                return animatedDrawable;
            }
        }
    }
    throw new UnsupportedOperationException("Unrecognized image class: " + image);
}
项目:fresco    文件:AnimatedSingleUsePostprocessorProducerTest.java   
@Test
public void testNonStaticBitmapIsPassedOn() {
  SingleUsePostprocessorConsumer postprocessorConsumer = produceResults();
  CloseableAnimatedImage sourceCloseableAnimatedImage = mock(CloseableAnimatedImage.class);
  CloseableReference<CloseableImage> sourceCloseableImageRef =
      CloseableReference.<CloseableImage>of(sourceCloseableAnimatedImage);
  postprocessorConsumer.onNewResult(sourceCloseableImageRef,res0.get());
  res0.close();

  verify(sourceCloseableAnimatedImage).close();
}
项目:fresco    文件:AnimatedRepeatedPostprocessorProducerTest.java   
@Test
public void testNonStaticBitmapIsPassedOn() {
  RepeatedPostprocessorConsumer postprocessorConsumer = produceResults();
  RepeatedPostprocessorRunner repeatedPostprocessorRunner = getRunner();

  CloseableAnimatedImage sourceCloseableAnimatedImage = mock(CloseableAnimatedImage.class);
  CloseableReference<CloseableImage> sourceCloseableImageRef =
      CloseableReference.<CloseableImage>of(sourceCloseableAnimatedImage);
  postprocessorConsumer.onNewResult(sourceCloseableImageRef,res0.get());
  res0.close();

  performCancelAndVerifyOnCancellation();
  verify(sourceCloseableAnimatedImage).close();
}
项目:GitHub    文件:AnimatedImageFactoryImpl.java   
private CloseableImage getCloseableImage(
    ImageDecodeOptions options,AnimatedImage image,Bitmap.Config bitmapConfig) {
  List<CloseableReference<Bitmap>> decodedFrames = null;
  CloseableReference<Bitmap> previewBitmap = null;
  try {
    final int frameForPreview = options.useLastFrameForPreview ? image.getFrameCount() - 1 : 0;
    if (options.forceStaticImage) {
      return new CloseableStaticBitmap(
          createPreviewBitmap(image,bitmapConfig,frameForPreview),ImmutableQualityInfo.FULL_QUALITY,0);
    }

    if (options.decodeAllFrames) {
      decodedFrames = decodeAllFrames(image,bitmapConfig);
      previewBitmap = CloseableReference.cloneOrNull(decodedFrames.get(frameForPreview));
    }

    if (options.decodePreviewFrame && previewBitmap == null) {
      previewBitmap = createPreviewBitmap(image,frameForPreview);
    }
    AnimatedImageResult animatedImageResult = AnimatedImageResult.newBuilder(image)
        .setPreviewBitmap(previewBitmap)
        .setFrameForPreview(frameForPreview)
        .setDecodedFrames(decodedFrames)
        .build();
    return new CloseableAnimatedImage(animatedImageResult);
  } finally {
    CloseableReference.closeSafely(previewBitmap);
    CloseableReference.closeSafely(decodedFrames);
  }
}
项目:GitHub    文件:AnimatedImageFactoryWebPImpltest.java   
@Test
public void testCreateDefaults() {
  WebPImage mockWebPImage = mock(WebPImage.class);

  // Expect a call to WebPImage.create
  TrivialPooledByteBuffer byteBuffer = createByteBuffer();
  when(mWebPImageMock.decode(byteBuffer.getNativePtr(),byteBuffer.size()))
      .thenReturn(mockWebPImage);

  EncodedImage encodedImage = new EncodedImage(
      CloseableReference.of(byteBuffer,FAKE_RESOURCE_RELEASER));
  encodedImage.setimageFormat(ImageFormat.UNKNowN);

  CloseableAnimatedImage closeableImage =
      (CloseableAnimatedImage) mAnimatedImageFactory.decodeWebP(
          encodedImage,ImageDecodeOptions.defaults(),DEFAULT_BITMAP_CONfig);

  // Verify we got the right result
  AnimatedImageResult imageResult = closeableImage.getimageResult();
  assertSame(mockWebPImage,imageResult.getimage());
  assertNull(imageResult.getPreviewBitmap());
  assertFalse(imageResult.hasDecodedFrame(0));

  // Should not have interacted with these.
  verifyZeroInteractions(mMockAnimatedDrawableBackendProvider);
  verifyZeroInteractions(mMockBitmapFactory);
}
项目:GitHub    文件:AnimatedImageFactoryGifImpltest.java   
@Test
public void testCreateDefaults() {
  GifImage mockGifImage = mock(GifImage.class);

  // Expect a call to GifImage.create
  TrivialPooledByteBuffer byteBuffer = createByteBuffer();
  when(mGifImageMock.decode(byteBuffer.getNativePtr(),byteBuffer.size()))
      .thenReturn(mockGifImage);

  EncodedImage encodedImage = new EncodedImage(
      CloseableReference.of(byteBuffer,FAKE_RESOURCE_RELEASER));
  encodedImage.setimageFormat(ImageFormat.UNKNowN);

  CloseableAnimatedImage closeableImage =
      (CloseableAnimatedImage) mAnimatedImageFactory.decodeGif(
          encodedImage,DEFAULT_BITMAP_CONfig);

  // Verify we got the right result
  AnimatedImageResult imageResult = closeableImage.getimageResult();
  assertSame(mockGifImage,imageResult.getimage());
  assertNull(imageResult.getPreviewBitmap());
  assertFalse(imageResult.hasDecodedFrame(0));

  // Should not have interacted with these.
  verifyZeroInteractions(mMockAnimatedDrawableBackendProvider);
  verifyZeroInteractions(mMockBitmapFactory);
}
项目:fresco    文件:AnimatedImageFactoryImpl.java   
private CloseableImage getCloseableImage(
    ImageDecodeOptions options,frameForPreview);
    }
    AnimatedImageResult animatedImageResult = AnimatedImageResult.newBuilder(image)
        .setPreviewBitmap(previewBitmap)
        .setFrameForPreview(frameForPreview)
        .setDecodedFrames(decodedFrames)
        .build();
    return new CloseableAnimatedImage(animatedImageResult);
  } finally {
    CloseableReference.closeSafely(previewBitmap);
    CloseableReference.closeSafely(decodedFrames);
  }
}
项目:fresco    文件:AnimatedImageFactoryWebPImpltest.java   
@Test
public void testCreateDefaults() {
  WebPImage mockWebPImage = mock(WebPImage.class);

  // Expect a call to WebPImage.create
  TrivialPooledByteBuffer byteBuffer = createByteBuffer();
  when(mWebPImageMock.decode(byteBuffer.getNativePtr(),imageResult.getimage());
  assertNull(imageResult.getPreviewBitmap());
  assertFalse(imageResult.hasDecodedFrame(0));

  // Should not have interacted with these.
  verifyZeroInteractions(mMockAnimatedDrawableBackendProvider);
  verifyZeroInteractions(mMockBitmapFactory);
}
项目:fresco    文件:AnimatedImageFactoryGifImpltest.java   
@Test
public void testCreateDefaults() {
  GifImage mockGifImage = mock(GifImage.class);

  // Expect a call to GifImage.create
  TrivialPooledByteBuffer byteBuffer = createByteBuffer();
  when(mGifImageMock.decode(byteBuffer.getNativePtr(),imageResult.getimage());
  assertNull(imageResult.getPreviewBitmap());
  assertFalse(imageResult.hasDecodedFrame(0));

  // Should not have interacted with these.
  verifyZeroInteractions(mMockAnimatedDrawableBackendProvider);
  verifyZeroInteractions(mMockBitmapFactory);
}
项目:GitHub    文件:ExperimentalBitmapAnimationDrawableFactory.java   
@Override
public boolean supportsImageType(CloseableImage image) {
  return image instanceof CloseableAnimatedImage;
}
项目:GitHub    文件:ExperimentalBitmapAnimationDrawableFactory.java   
@Override
public AnimatedDrawable2 createDrawable(CloseableImage image) {
  return new AnimatedDrawable2(
      createAnimationBackend(
          ((CloseableAnimatedImage) image).getimageResult()));
}
项目:GitHub    文件:AnimatedImageFactoryWebPImpltest.java   
@Test
public void testCreateWithPreviewBitmap() throws Exception {
  WebPImage mockWebPImage = mock(WebPImage.class);

  Bitmap mockBitmap = MockBitmapFactory.create(50,50,DEFAULT_BITMAP_CONfig);

  // Expect a call to WebPImage.create
  TrivialPooledByteBuffer byteBuffer = createByteBuffer();
  when(mWebPImageMock.decode(byteBuffer.getNativePtr(),byteBuffer.size()))
      .thenReturn(mockWebPImage);
  when(mockWebPImage.getWidth()).thenReturn(50);
  when(mockWebPImage.getHeight()).thenReturn(50);

  // For decoding preview frame,expect some calls.
  final AnimatedDrawableBackend mockAnimatedDrawableBackend =
      createAnimatedDrawableBackendMock(1);

  when(mMockAnimatedDrawableBackendProvider.get(
          any(AnimatedImageResult.class),isNull(Rect.class)))
      .thenReturn(mockAnimatedDrawableBackend);
  when(mMockBitmapFactory.createBitmapInternal(50,DEFAULT_BITMAP_CONfig))
      .thenReturn(CloseableReference.of(mockBitmap,FAKE_BITMAP_RESOURCE_RELEASER));
  AnimatedImageCompositor mockCompositor = mock(AnimatedImageCompositor.class);
  powermockito.whenNew(AnimatedImageCompositor.class)
      .withAnyArguments()
      .thenReturn(mockCompositor);

  ImageDecodeOptions imageDecodeOptions = ImageDecodeOptions.newBuilder()
      .setDecodePreviewFrame(true)
      .build();
  EncodedImage encodedImage = new EncodedImage(
      CloseableReference.of(byteBuffer,FAKE_RESOURCE_RELEASER));
  encodedImage.setimageFormat(ImageFormat.UNKNowN);
  CloseableAnimatedImage closeableImage =
      (CloseableAnimatedImage) mAnimatedImageFactory.decodeWebP(
          encodedImage,imageDecodeOptions,imageResult.getimage());
  assertNotNull(imageResult.getPreviewBitmap());
  assertFalse(imageResult.hasDecodedFrame(0));

  // Should not have interacted with these.
  verify(mMockAnimatedDrawableBackendProvider).get(
      any(AnimatedImageResult.class),isNull(Rect.class));
  verifyNoMoreInteractions(mMockAnimatedDrawableBackendProvider);
  verify(mMockBitmapFactory).createBitmapInternal(50,DEFAULT_BITMAP_CONfig);
  verifyNoMoreInteractions(mMockBitmapFactory);
  verify(mockCompositor).renderFrame(0,mockBitmap);
}
项目:GitHub    文件:AnimatedImageFactoryWebPImpltest.java   
@Test
public void testCreateWithDecodeAlFrames() throws Exception {
  WebPImage mockWebPImage = mock(WebPImage.class);

  Bitmap mockBitmap1 = MockBitmapFactory.create(50,DEFAULT_BITMAP_CONfig);
  Bitmap mockBitmap2 = MockBitmapFactory.create(50,expect some calls.
  final AnimatedDrawableBackend mockAnimatedDrawableBackend =
      createAnimatedDrawableBackendMock(2);
  when(
      mMockAnimatedDrawableBackendProvider.get(
          any(AnimatedImageResult.class),isNull(Rect.class)))
      .thenReturn(mockAnimatedDrawableBackend);

  when(mMockBitmapFactory.createBitmapInternal(50,DEFAULT_BITMAP_CONfig))
      .thenReturn(CloseableReference.of(mockBitmap1,FAKE_BITMAP_RESOURCE_RELEASER))
      .thenReturn(CloseableReference.of(mockBitmap2,FAKE_BITMAP_RESOURCE_RELEASER));
  AnimatedImageCompositor mockCompositor = mock(AnimatedImageCompositor.class);
  powermockito.whenNew(AnimatedImageCompositor.class)
      .withAnyArguments()
      .thenReturn(mockCompositor);

  ImageDecodeOptions imageDecodeOptions = ImageDecodeOptions.newBuilder()
      .setDecodePreviewFrame(true)
      .setDecodeAllFrames(true)
      .build();

  EncodedImage encodedImage = new EncodedImage(
      CloseableReference.of(byteBuffer,imageResult.getimage());
  assertNotNull(imageResult.getDecodedFrame(0));
  assertNotNull(imageResult.getDecodedFrame(1));
  assertNotNull(imageResult.getPreviewBitmap());

  // Should not have interacted with these.
  verify(mMockAnimatedDrawableBackendProvider).get(
      any(AnimatedImageResult.class),isNull(Rect.class));
  verifyNoMoreInteractions(mMockAnimatedDrawableBackendProvider);
  verify(mMockBitmapFactory,times(2)).createBitmapInternal(50,mockBitmap1);
  verify(mockCompositor).renderFrame(1,mockBitmap2);
}
项目:GitHub    文件:AnimatedImageFactoryGifImpltest.java   
@Test
public void testCreateWithPreviewBitmap() throws Exception {
  GifImage mockGifImage = mock(GifImage.class);

  Bitmap mockBitmap = MockBitmapFactory.create(50,DEFAULT_BITMAP_CONfig);

  // Expect a call to WebPImage.create
  TrivialPooledByteBuffer byteBuffer = createByteBuffer();
  when(mGifImageMock.decode(byteBuffer.getNativePtr(),byteBuffer.size()))
      .thenReturn(mockGifImage);
  when(mockGifImage.getWidth()).thenReturn(50);
  when(mockGifImage.getHeight()).thenReturn(50);

  // For decoding preview frame,expect some calls.
  final AnimatedDrawableBackend mockAnimatedDrawableBackend =
      createAnimatedDrawableBackendMock(1);
  when(mMockAnimatedDrawableBackendProvider.get(
      any(AnimatedImageResult.class),FAKE_RESOURCE_RELEASER));
  encodedImage.setimageFormat(ImageFormat.UNKNowN);
  CloseableAnimatedImage closeableImage =
      (CloseableAnimatedImage) mAnimatedImageFactory.decodeGif(
          encodedImage,mockBitmap);
}
项目:GitHub    文件:AnimatedImageFactoryGifImpltest.java   
@Test
public void testCreateWithDecodeAlFrames() throws Exception {
  GifImage mockGifImage = mock(GifImage.class);

  Bitmap mockBitmap1 = MockBitmapFactory.create(50,DEFAULT_BITMAP_CONfig);

  // Expect a call to GifImage.create
  TrivialPooledByteBuffer byteBuffer = createByteBuffer();
  when(mGifImageMock.decode(byteBuffer.getNativePtr(),expect some calls.
  final AnimatedDrawableBackend mockAnimatedDrawableBackend =
      createAnimatedDrawableBackendMock(2);

  when(
      mMockAnimatedDrawableBackendProvider.get(
          any(AnimatedImageResult.class),mockBitmap2);
}
项目:fresco    文件:ExperimentalBitmapAnimationDrawableFactory.java   
@Override
public boolean supportsImageType(CloseableImage image) {
  return image instanceof CloseableAnimatedImage;
}
项目:fresco    文件:ExperimentalBitmapAnimationDrawableFactory.java   
@Override
public AnimatedDrawable2 createDrawable(CloseableImage image) {
  return new AnimatedDrawable2(
      createAnimationBackend(
          ((CloseableAnimatedImage) image).getimageResult()));
}
项目:fresco    文件:AnimatedImageFactoryWebPImpltest.java   
@Test
public void testCreateWithPreviewBitmap() throws Exception {
  WebPImage mockWebPImage = mock(WebPImage.class);

  Bitmap mockBitmap = MockBitmapFactory.create(50,mockBitmap);
}
项目:fresco    文件:AnimatedImageFactoryWebPImpltest.java   
@Test
public void testCreateWithDecodeAlFrames() throws Exception {
  WebPImage mockWebPImage = mock(WebPImage.class);

  Bitmap mockBitmap1 = MockBitmapFactory.create(50,mockBitmap2);
}
项目:fresco    文件:AnimatedImageFactoryGifImpltest.java   
@Test
public void testCreateWithPreviewBitmap() throws Exception {
  GifImage mockGifImage = mock(GifImage.class);

  Bitmap mockBitmap = MockBitmapFactory.create(50,mockBitmap);
}
项目:fresco    文件:AnimatedImageFactoryGifImpltest.java   
@Test
public void testCreateWithDecodeAlFrames() throws Exception {
  GifImage mockGifImage = mock(GifImage.class);

  Bitmap mockBitmap1 = MockBitmapFactory.create(50,mockBitmap2);
}
项目:CanPhotos    文件:CanViewPagerActivity.java   
private void handleAnimateBitmap(CloseableAnimatedImage animatedImage,int position) {

        AnimatedDrawableFactory animatedDrawableFactory =
                Fresco.getimagePipelineFactory().getAnimatedDrawableFactory();
        AnimatedDrawable drawable =
                animatedDrawableFactory.create(animatedImage.getimageResult());

        Bitmap bitmap = drawable2Bitmap(drawable);
        map.put(position,bitmap);


    }

com.facebook.react.views.image.ImageResizeMode的实例源码

com.facebook.react.views.image.ImageResizeMode的实例源码

项目:RNLearn_Project1    文件:RCtimageView.java   
@H_301_7@
@ReactProp(name = ViewProps.RESIZE_MODE)
public void setResizeMode(@Nullable String resizeMode) {
  ScaleType scaleType = ImageResizeMode.toScaleType(resizeMode);
  if (mDrawImage.getScaleType() != scaleType) {
    getMutableDrawImage().setScaleType(scaleType);
  }
}

com.facebook.react.views.image.ReactImageManager的实例源码

com.facebook.react.views.image.ReactImageManager的实例源码

项目:react-native-gcm-android    文件:MainReactPackage.java   
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
    return Arrays.<ViewManager>asList(
            new ReactDrawerLayoutManager(),new ReacthorizontalscrollviewManager(),new ReactimageManager(),new ReactProgressBarViewManager(),new ReactRawTextManager(),new ReactScrollViewManager(),new ReactSwitchManager(),new ReactTextInputManager(),new ReactTextViewManager(),new ReactToolbarManager(),new ReactViewManager(),new ReactViewPagerManager(),new ReactTextInlineImageViewManager(),new ReactVirtualTextViewManager(),new SwipeRefreshLayoutManager(),new ReactWebViewManager());
}
项目:ReactNativeSignatureExample    文件:MainReactPackage.java   
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
  return Arrays.<ViewManager>asList(
    ARTRenderableViewManager.createARTGroupViewManager(),ARTRenderableViewManager.createARTShapeViewManager(),ARTRenderableViewManager.createARTTextViewManager(),new ARTSurfaceViewManager(),new ReactDialogPickerManager(),new ReactDrawerLayoutManager(),new ReactDropdownPickerManager(),new FrescoBasedReactTextInlineImageViewManager(),new ReactWebViewManager(),new RecyclerViewBackedScrollViewManager(),new SwipeRefreshLayoutManager());
}
项目:react-native-ibeacon-android    文件:MainReactPackage.java   
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
  return Arrays.<ViewManager>asList(
    ARTRenderableViewManager.createARTGroupViewManager(),new SwipeRefreshLayoutManager());
}
项目:react-native-Box-loaders    文件:MainReactPackage.java   
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
  return Arrays.<ViewManager>asList(
    ARTRenderableViewManager.createARTGroupViewManager(),new ReactModalHostManager(),new ReactSliderManager(),new SwipeRefreshLayoutManager());
}
项目:Ironman    文件:MainReactPackage.java   
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
  return Arrays.<ViewManager>asList(
    ARTRenderableViewManager.createARTGroupViewManager(),new SwipeRefreshLayoutManager());
}
项目:RNLearn_Project1    文件:MainReactPackage.java   
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
  List<ViewManager> viewManagers = new ArrayList<>();

  viewManagers.add(ARTRenderableViewManager.createARTGroupViewManager());
  viewManagers.add(ARTRenderableViewManager.createARTShapeViewManager());
  viewManagers.add(ARTRenderableViewManager.createARTTextViewManager());
  viewManagers.add(new ARTSurfaceViewManager());
  viewManagers.add(new ReactDialogPickerManager());
  viewManagers.add(new ReactDrawerLayoutManager());
  viewManagers.add(new ReactDropdownPickerManager());
  viewManagers.add(new ReacthorizontalscrollviewManager());
  viewManagers.add(new ReactimageManager());
  viewManagers.add(new ReactModalHostManager());
  viewManagers.add(new ReactProgressBarViewManager());
  viewManagers.add(new ReactRawTextManager());
  viewManagers.add(new ReactScrollViewManager());
  viewManagers.add(new ReactSliderManager());
  viewManagers.add(new ReactSwitchManager());
  viewManagers.add(new FrescoBasedReactTextInlineImageViewManager());
  viewManagers.add(new ReactTextInputManager());
  viewManagers.add(new ReactTextViewManager());
  viewManagers.add(new ReactToolbarManager());
  viewManagers.add(new ReactViewManager());
  viewManagers.add(new ReactViewPagerManager());
  viewManagers.add(new ReactVirtualTextViewManager());
  viewManagers.add(new ReactWebViewManager());
  viewManagers.add(new SwipeRefreshLayoutManager());

  SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(reactContext);
  if (preferences.getBoolean("flat_uiimplementation",false)) {
    viewManagers.addAll(Arrays.asList(
      new RCTViewManager(),new RCTTextManager(),new RCTRawTextManager(),new RCTVirtualTextManager(),new RCTTextInlineImageManager(),new RCtimageViewManager(),new RCTTextInputManager(),new RCTViewPagerManager(),new FlatARTSurfaceViewManager(),new RCTModalHostManager()));
  }

  return viewManagers;
}

今天关于如何设计一个好用的 React Image 组件?react组件设计原则的讲解已经结束,谢谢您的阅读,如果想了解更多关于Android 设计一个菱形形状的Imageview组件.、com.facebook.imagepipeline.image.CloseableAnimatedImage的实例源码、com.facebook.react.views.image.ImageResizeMode的实例源码、com.facebook.react.views.image.ReactImageManager的实例源码的相关知识,请在本站搜索。

本文标签:

上一篇TypeScript高级类型备忘录(附示例)(高级备忘录下载)

下一篇你的第一个 Docker + React 全栈应用(docker部署react)