android 实现类似微信缓存和即时更新好友头像
引言
使用微信时我们会发现,首次进入微信的好友列表时,会加载好友头像,但是再次进入时,就不用重新加载了,而且其他页面都不用重新加载,说明微信的好友头像是缓存在本地的,然后好友修改头像后,又会及时的更新,这个功能是如何实现的呢,我们来分析一下
分析
关于头像缓存的实现
头像是网络图片,而且数据量较大,如果用我们常用的SharedPreferences将头像以Bitmap的形式存储,势必会造成OOM,这个方法是行不通的,我们存储的只能是图片的地址,但是如果只存储地址的话,要转化成图片,还是要通过网络请求重新加载,达不到我们要求的效果,所以我们需要在磁盘中单独开辟一块空间,将头像以Bitmap的形式进行存储,如何实现呢?其实关于网络图片的缓存,有很多开源的第三方框架,比较可靠好用的如xUtils,Glide,volley,Universal-Image-Loader,Picasso,Fresco等等。
下面我们以常用的xUtils为例
首先对BitmapUtils的实例化,对于磁盘缓存路径,磁盘缓存空间大小,内存缓存的空间大小,内存缓存百分比可以自定义,也可以使用默认配置,代码如下:
/**
* @param context 上下文
*/
public BitmapUtils(Context context) {
this(context, null);
} /**
* @param context 上下文
* @param diskCachePath 磁盘高速缓存路径
*/
public BitmapUtils(Context context, String diskCachePath) {
if (context == null) {
throw new IllegalArgumentException("context may not be null");
} this.context = context.getApplicationContext();
globalConfig = BitmapGlobalConfig.getInstance(this.context, diskCachePath);
defaultDisplayConfig = new BitmapDisplayConfig();
} /**
*
* @param context 上下文
* @param diskCachePath 磁盘高速缓存路径
* @param memoryCacheSize 内存缓存空间大小
*/
public BitmapUtils(Context context, String diskCachePath, int memoryCacheSize) {
this(context, diskCachePath);
globalConfig.setMemoryCacheSize(memoryCacheSize);
} /**
*
* @param context 上下文
* @param diskCachePath 磁盘高速缓存路径
* @param memoryCacheSize 内存缓存空间大小
* @param diskCacheSize 磁盘高速缓存空间大小
*/
public BitmapUtils(Context context, String diskCachePath, int memoryCacheSize, int diskCacheSize) {
this(context, diskCachePath);
globalConfig.setMemoryCacheSize(memoryCacheSize);
globalConfig.setDiskCacheSize(diskCacheSize);
} /**
*
* @param context 上下文
* @param diskCachePath 磁盘高速缓存路径
* @param memoryCachePercent 内存缓存百分比
*/
public BitmapUtils(Context context, String diskCachePath, float memoryCachePercent) {
this(context, diskCachePath);
globalConfig.setMemCacheSizePercent(memoryCachePercent);
}
/**
*
* @param context 上下文
* @param diskCachePath 磁盘高速缓存路径
* @param memoryCachePercent 内存缓存百分比
* @param diskCacheSize 磁盘缓存空间大小
*/
public BitmapUtils(Context context, String diskCachePath, float memoryCachePercent, int diskCacheSize) {
this(context, diskCachePath);
globalConfig.setMemCacheSizePercent(memoryCachePercent);
globalConfig.setDiskCacheSize(diskCacheSize);
}
一般情况下,我们只需要使用默认配置就可以了,即
BitmapUtils bitmap = new BitmapUtils(context);
然后对图片的缓存和显示
/**
* 根据图片路径,显示到具体的View上
* @param container 要把图片显示到的View
* @param uri 图片路径
*/
public <T extends View> void display(T container, String uri) {
display(container, uri, null, null);
} /**
* 根据图片路径,显示到具体的View上
* @param container 要把图片显示到的View
* @param uri 图片路径
* @param displayConfig
*/
public <T extends View> void display(T container, String uri, BitmapDisplayConfig displayConfig) {
display(container, uri, displayConfig, null);
} /**
* 根据图片路径,显示到具体的View上
* @param container 要把图片显示到的View
* @param uri 图片路径
* @param callBack 加载过程回调各种状态
*/
public <T extends View> void display(T container, String uri, BitmapLoadCallBack<T> callBack) {
display(container, uri, null, callBack);
} /**
* 根据图片路径,显示到具体的View上
* @param container 要把图片显示到的View
* @param uri 图片路径
* @param displayConfig 位图显示配置
* @param callBack
*/
public <T extends View> void display(T container, String uri, BitmapDisplayConfig displayConfig, BitmapLoadCallBack<T> callBack) {
if (container == null) {
return;
} if (callBack == null) {
callBack = new DefaultBitmapLoadCallBack<T>();
} if (displayConfig == null || displayConfig == defaultDisplayConfig) {
displayConfig = defaultDisplayConfig.cloneNew();
}
// Optimize Max
BitmapSize size = displayConfig.getBitmapMaxSize();SizedisplayConfig.setBitmapMaxSize(BitmapCommonUtils.optimizeMaxSizeByView(container, size.getWidth(), size.getHeight())); container.clearAnimation(); if (TextUtils.isEmpty(uri)) {
callBack.onLoadFailed(container, uri, displayConfig.getLoadFailedDrawable());
return;
} // start loading
callBack.onPreLoad(container, uri, displayConfig); // find bitmap from mem cache.
Bitmap bitmap = globalConfig.getBitmapCache().getBitmapFromMemCache(uri, displayConfig); if (bitmap != null) {
callBack.onLoadStarted(container, uri, displayConfig);
callBack.onLoadCompleted(
container,
uri,
bitmap,
displayConfig,
BitmapLoadFrom.MEMORY_CACHE);
} else if (!bitmapLoadTaskExist(container, uri, callBack)) { final BitmapLoadTask<T> loadTask = new BitmapLoadTask<T>(container, uri, displayConfig, callBack); // get executor
PriorityExecutor executor = globalConfig.getBitmapLoadExecutor();
File diskCacheFile = this.getBitmapFileFromDiskCache(uri);
boolean diskCacheExist = diskCacheFile != null && diskCacheFile.exists();
if (diskCacheExist && executor.isBusy()) {
executor = globalConfig.getDiskCacheExecutor();
}
// set loading image
Drawable loadingDrawable = displayConfig.getLoadingDrawable();
callBack.setDrawable(container, new AsyncDrawable<T>(loadingDrawable, loadTask)); loadTask.setPriority(displayConfig.getPriority());
loadTask.executeOnExecutor(executor);
}
}
从这段代码中我们可以看到,当要加载某张图片时,会根据图片地址进行查找是否有对应的bitmap缓存图片,如果有就直接引用缓存,如果没有就加载并缓存,所以我们对图片的缓存只需要实现以上方法就可以了,而且只要设置相同的缓存路径,就可以实现一个页面缓存后,其他页面有相同图片也可以调用。那么缓存之后,好友更新头像,又是怎么做到即时更新的呢?
缓存后如何实现即时更新头像
根据查阅的资料,可以归结为以下几种实现方式:
1.在服务器返回用户数组时多加一个字段头像最后一次修改时间或者修改过几次等标志符,与缓存进行比较,是否有变化
2.利用图片的checkSum来实现,如果check到这个数字有变化,就会自动去更新
3.利用socket监听,当好友头像更新时候首先会告诉服务器,服务器将变化通知推送到所有好友,好友监听收到通知后自动更新
第一种方法和第二种方法本质是一致的,通过请求服务器的数据与本地缓存进行对比,是由客户端处理的,第三种方法的话你换一次头像就要服务器去提醒你的所有好友一遍,服务器压力会不会比较大
仔细去研究一下微信,就会发现,当好友头像修改后,如果你停留在某个页面,进入的这个页面是之前进入过的,还没有销毁,头像是不会改变的,你需要打开一个新的页面或者重新进入微信,才会更新头像,由此看出,微信并不是用的第三种方式,而是采用了前两种方式的实现原理,只有在创建一个Activity或fragment时,调用接口,读取服务器数据时才会更新头像
总结
通过以上的分析,我们基本捋清了思路,要实现类似微信的缓存和更新还有头像,先是在磁盘开辟一个空间,用于读写头像的Bitmap,然后创建页面时,读取服务器数据和本地缓存进行比较,如果有变化就进行更新
android 实现类似微信缓存和即时更新好友头像的更多相关文章
- Android 实现类似微信客户端朋友圈更新提示的小红点&栏目订阅
用到的类: com.jauker.widget.BadgeView 实现代码: BadgeView imageBadge = new BadgeView(getContext()); imageBad ...
- Android手机清除微信缓存
方法一: 1.任意找一个微信好友,给他发送网址 http://debugx5.qq.com 2.自己点击这个网址跳转 3.进入后看到下面的页面,通过勾选第二张截图的Cookie和文件缓存来清除微信缓存 ...
- Android封装类似微信的顶部TitleBar弹出的PopupWindow代码
Android仿微信顶部titlebar,点击加号弹出的PopupWindow,是封装好的PopupWindow,直接拿来用即可,先看效果图: 调用代码非常简单,这是MainActivity的代码: ...
- [Android]实现类似微信的延迟加载的Fragment——LazyFragment
以下内容为原创,转载请注明: 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/4303910.html 参考微信,使用ViewPager来显示不同的t ...
- Android 高逼格纯代码实现类似微信钱包带分割线的GridView
前言 原文地址:http://blog.csdn.net/sk719887916/article/details/40348837: Tamic 通过上两篇关于自定view的文章,在自定义vie ...
- Android 高仿微信即时聊天 百度云为基础的推
转载请注明出处:http://blog.csdn.net/lmj623565791/article/details/38799363 ,本文出自:[张鸿洋的博客] 一直在仿微信界面,今天最终有幸利用百 ...
- 【Android】解决微信调起支付接口没反应,调不起来微信的问题
原文:[Android]解决微信调起支付接口没反应,调不起来微信的问题 //#前言 吐槽一下,微信支付的sdk真难用,文档混乱,坑不少. 正文:可能引起这种情况的问题 1. 最不能出现的 你的APPI ...
- 用SQLite查看编辑android导出的微信聊天记录
上一篇我们已经能够完成文字版微信聊天记录导出android了,也即复制或剪切MicroMsg.db文件到电脑,以.db格式结尾的文件是数据库文件(database document),需要安装相关数据 ...
- Android公共库——图片缓存 网络缓存 下拉及底部更多ListView 公共类
Android公共库——图片缓存 网络缓存 下拉及底部更多ListView 公共类 转载自http://www.trinea.cn/android/android-common-lib/ 介绍总结的一 ...
随机推荐
- sql拼接列字符串
1.使用函数(sql2000以上) )) ) AS BEGIN ) select @v = isnull(@v + ',','')+code FROM dict WHERE type=@filter ...
- 颠覆我的Thread.join()
学而时习之,不亦说乎! --<论语> 为什么说是颠覆? 1)任何对象都可以作为锁对象,锁对象的行为都是一样的吗?之前我一直认为锁对 ...
- python __getattribute__、__getattr__、__setattr__详解
__getattribute__ 官方文档中描述如下: 该方法可以拦截对对象属性的所有访问企图,当属性被访问时,自动调用该方法(只适用于新式类).因此常用于实现一些访问某属性时执行一段代码的特性. 需 ...
- 《JavaScript编程精解》读书笔记
第一章 JavaScript基础:值.变量.控制流程 JavaScript里有六种基本类型:number类型.string类型.boolean类型.object.function和undefined. ...
- (转)Linux服务器SNMP常用OID
原文:https://www.haiyun.me/archives/linux-snmp-oid.html 收集整理一些Linux下snmp常用的OID,用做服务器监控很不错.服务器负载: 1 2 3 ...
- [Android]Caused by: java.lang.IllegalArgumentException: Service not registered.md
Caused by: java.lang.IllegalArgumentException: Service not registered: org.diql.aidldemo.MainActivit ...
- 运行时用AnimatorOverrideController动态加载动画片段
https://blog.csdn.net/tlrainty/article/details/54602786 项目中经常会遇到这种情况:很多模型动画的AnimatorController是一模一样的 ...
- 在ubuntu下使用Eclipse搭建Hadoop开发环境
一.安装准备1.JDK版本:jdk1.7.0(jdk-7-linux-i586.tar.gz)2.hadoop版本:hadoop-1.1.1(hadoop-1.1.1.tar.gz)3.eclipse ...
- DateTime.Now与DateTime.Today的区别
区别如下图: DateTime.Now: 不仅显示日期 还显示当前时间: DateTime.Today: 只显示当前日期,没有时间
- Python基础(9) - 类
Python 看下面一个简单类: >>> class MyClass(object): ... """ ... this is a class with ...