博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
React Native中的图片缓存详解(二)
阅读量:4086 次
发布时间:2019-05-25

本文共 3840 字,大约阅读时间需要 12 分钟。

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

本项目来自  文章来自江清清的技术专栏()

原文地址(需要翻墙):

1.基本介绍

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

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:
""
,
      
medium:
""
,
      
small:
""
    
}
  
}
}

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

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的实现效果代码可以在库中找到

3.静态资源图片处理

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

1
2
3
4
5
6
7
8
/*
 
* Generated by
 
*/
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丶清() 侵权必究!

你可能感兴趣的文章
Nginx篇-Nginx配置动静分离
查看>>
缓存篇-Redis缓存失效以及解决方案
查看>>
缓存篇-使用Redis进行分布式锁应用
查看>>
缓存篇-Redisson的使用
查看>>
phpquery抓取网站内容简单介绍
查看>>
找工作准备的方向(4月22日写的)
查看>>
关于fwrite写入文件后打开查看是乱码的问题
查看>>
用结构体指针前必须要用malloc,不然会出现段错误
查看>>
Linux系统中的美
查看>>
一些实战项目(linux应用层编程,多线程编程,网络编程)
查看>>
我觉得专注于去学东西就好了,与世无争。
查看>>
原来k8s docker是用go语言写的,和现在所讲的go是一个东西!
查看>>
STM32CubeMX 真的不要太好用
查看>>
STM32CubeMX介绍、下载与安装
查看>>
不要买铝合金机架的无人机,不耐摔,易变形弯曲。
查看>>
ACfly也是基于FreeRTOS的
查看>>
F330装GPS的位置
查看>>
pixhawk也可以用Airsim仿真
查看>>
《无人机电机与电调技术》可以看看
查看>>
我发现七月在线的GAAS课程基本都讲到了
查看>>