zl程序教程

您现在的位置是:首页 >  后端

当前栏目

React Native中的图片缓存详解(二)

缓存React 详解 图片 native
2023-09-27 14:29:02 时间

尊重版权,未经授权不得转载

本项目来自wcandillon  文章来自江清清的技术专栏(http://www.lcode.org)

原文地址(需要翻墙):https://hackernoon.com/image-caching-in-react-native-96d8df33ca84#.uaznyr11h

1.基本介绍

我最近正在开发一个React Native项目,同时想要给大家分享一个方法库,可以在图片显示的时候更加的平滑,以此来提升用户体验。该使用的库就是react-native-img-cache 项目实现的效果如下:

React Native交流10群:157867561,欢迎各位大牛,React Native技术爱好者加入交流!同时博客右侧欢迎微信扫描关注订阅号,移动技术干货,精彩文章技术推送!

以上的动态效果中,会有头像,列表上面的图片等多种图片类型,在本项目中采用

2.用户上传的图片处理

针对用户自定义生成的图片(例如:app的用户上传的图片),我们有两种缓存策略:immmutable和mutable。immutable缓存策略用于图片地址不变的情况,反正mutable用于图片地址经常变化的情况。但是我们为什么同时需要这两种策略呢?让我们来看下面的用户配置项。

如上界面效果:当我们现实用于资料头像的时候,该图片通过后台服务器提供。然后当我们需要显示列表中的图像信息的时候,只需要显示用户头像的缩略图即可,并不需要发送额外的请求到服务器。

不可变的图片需要依靠后台服务器提供的最新图片的URL地址,在上面个人头像的案例中,后台可能会返回如下的信息:

?
1
2
3
4
5
6
7
8
9
{
   profile: {
     pictures: {
       large: "http://path-to-image/uid.jpg" ,
       medium: "http://path-to-image/uid.jpg" ,
       small: "http://path-to-image/uid.jpg"
     }
   }
}

缓存这些头像图片是非常简单便捷的,通过图片URL地址的哈希串号,我们可以检测本地缓存文件中是否存在该图片,然后进行相关处理。下面就是采用react-native-fetch-blob库下载图片,然后进行缓存处理的实例。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import RNFetchBlob from "react-native-fetch-blob" ;
const SHA1 = require( "crypto-js/sha1" );
 
export default class ImageCache {
   static function get(uri: string): Promise<string> {
     const path = RNFetchBlob.fs.dirs.CacheDir + "_immutable_images/" + SHA1(uri) + ".jpg" ;
     return RNFetchBlob.fs.exists(path).then(exists => {
       if (exists) {
         return path;
       } else {
         return RNFetchBlob.config({ path })
                 .fetch( "GET" , uri, {})
                 .then(() => path);
       }
     });
   }
}

针对可变的图片,我们需要实现一个observable接口。针对APP应用中的每一个URL,该监听着会观察到在本地缓存中的图片当前的路径。如果图片被下载,那么该观察者就会收到图片的本地当前路径。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
type ImageCacheObserver = (path: string) => void;
 
interface IImageCacheObservable {
   on(uri: string, observer: ImageCacheObserver);
   dispose(observer: ImageCacheObserver);
}
 
interface IImageCache extends IImageCacheObservable {
   /*
    * When busting an URI, the new local path of the image will
    * be provided to all its observers
    */
   bust(uri: string);
}

下面的代码片段显示了如何在React Native组件实现IIMageCache的方法。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
interface CachedImageProps {
     uri: string;
     style?: React.ImageStyle;
}
 
@observer
export class CachedImage extends Component<CachedImageProps, void>  {
 
     @observable private _path;
     private handler = path => this .path = path;
 
     @computed get path() { return this ._path; }
     set path(path: string) { return this ._path = path; }
 
     observe(uri: string) {
       // We start observing the cache
       ImageCache.on(uri, handler): 
     }
 
     componentWillMount() {
         observe( this .props.uri);
     }
 
     componentWillReceiveProps(nextProps: CachedImageProps) {
         observe(nextProps.uri);
     }
 
     componentWillUnmount() {
       // We stop observing the cache
       ImageCache.dispose(handler);
     }
 
     render() {
         const {style} = this .props;
         return <Image style={style}
                       source={{ uri: this .store.path }}>{ this .props.children}</Image>;
     }
}

实现IImageCache接口类,可以实现同时不下载相同的图片。同时在接口方法中添加一个额外的immutable的参数来进行设置缓存策略。

?
1
2
3
4
5
interface IImageCacheObservable {
   // The immutable parameter indicates which caching strategy to use
   on(uri: string, observer: ImageCacheObserver, immutable: boolean);
   dispose(observer: ImageCacheObserver);
}

针对具体的ImageCache的实现效果代码可以在react-native-img-cache库中找到

3.静态资源图片处理

针对静态图片资源,同时这边也提供一个小小的react-native-static-images库用来扫描应用的图片文件夹,然后生成包含应用中所有的静态图片资源的类。可以看如下一个实例:

?
1
2
3
4
5
6
7
8
/*
  */
export default class Images {
     static readonly resetPassword = require( "../public/images/ResetPassword.jpg" );
     static readonly signIn = require( "../public/images/SignIn.jpg" );
     static readonly signUp = require( "../public/images/SignUp.jpg" );
}

但是如果用户使用的是旧版本的应用,后台可能会引用到部分静态资源,但是这些图片没有在已安装的应用中。如果是这种情况,那我们就必须下载远程图片了,具体做法如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
export default class {
   static getImage(id: string): any {
         // We check if the image is present within the app bundle
         const entry: any = _.get(Images, _.camelCase(id));
         if (entry !== undefined) {
             return entry;
         } else {
             // If not, we return a remote link for that image
             return { uri: `${StaticDomain}/${id}` };
         }
     }
}

React Native交流10群:157867561,欢迎各位大牛,React Native技术爱好者加入交流!同时博客右侧欢迎微信扫描关注订阅号,移动技术干货,精彩文章技术推送!

尊重原创,转载请注明:From Sky丶清(http://www.lcode.org) 侵权必究!