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,然后创建页面时,读取服务器数据和本地缓存进行比较,如果有变化就进行更新

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android仿微信、QQ附近好友雷达扫描效果

    1.概述 最近一直到在带实习生,因为人比较多,所以很长一段时间没有更新博客了,今天更新一篇雷达扫描附近好友效果,以后尽量每周更新一篇,先看一下效果: 2.实现 1.效果分析 效果分为两个部分,一个是上半部分的自定义RadarView,还有就是下半部分的ViewPager,至于怎么做到缩放和背景虚化的效果大家可以去看看LazyViewPager这里不详细介绍,这里主要实现扫描效果部分. 2.扫描效果实现 2.1自定义RadarView在onDraw()方法中画六个圆圈,至于圆圈的半径是多少我们需要

  • Android仿微信雷达辐射搜索好友(逻辑清晰实现简单)

    不知不觉这个春节也已经过完了,遗憾家里没网,没能及时给大家送上祝福,今天回到深圳,明天就要上班了,小伙伴们是不是和我一样呢?今天讲的是一个大家都见过的动画,雷达搜索好友嘛,原理也十分的简单,你看完我的分析,也会觉得很简单了,国际惯例,无图无真相,我们先看看效果图,对了,真 测试机送人了,所讲这段时间应该一直用模拟器显示吧! 仿微信雷达扫描,仿安卓微信.云播雷达扫描动画效果点击中间的黑色圆圈开始扫描动画,再次点击复位,需要这种效果的朋友可以自己下载看一下. 效果图如下所示: 这个界面相信大家都认识

  • Android仿微信@好友功能 输入@跳转、删除整块

    最近在做聊天功能的时候,有一个需求是仿照微信做@好友的功能,本来以为挺简单,但是做到这块的时候,发现和想象的有点不一样,什么整块删除,块可编辑,总之,加个@的功能很简单,但是要做和微信的一样还是费了一些功夫,下面是一个demo仅供参考,防止遗忘 先上个效果图 就是这么个功能 1. 分析需求 输入@跳转到联系人界面,选中一个或者多个好友返回到当前界面 按退格键删除整块内容 块内的内容可编辑,编辑完了之后将不附带@功能,只是单纯的文字 2. 开始编码 既然是文本输入首先继承EditText自定义一个

  • Android实现分享微信好友及出现闪退的解决办法

     1.申请微信APPID 要实现分享到微信的功能,首先要到微信开放平台申请一个APPID.但在申请APPID的时候需要填写一个应用签名和应用包名.需要注意的是包名必须与开发应用时的包名一致,应用签名也必须去掉冒号而且字母为小写. 2.应用签名的获取 开发android应用的人很多,很有可能类名.包名起成了同一个名字,签名这时候就起到区分的作用. 所有的Android应用都必须有数字签名,不存在没有数字签名的应用,包括模拟器运行的.模拟器开发环境,开发时,通过ADB接口上传的程序会自动被签有Deb

  • Android中使用ListView模拟微信好友功能

    效果图: 分析: 1.创建listView 2.创建数据 3.创建适配器 将数据放到呈现数据的容器里面. 将这个容器(带数据)连接适配器. 其实是直接在我们自己写的adapter的getView重载方法中返回连接的view. View view=View.inflate(mContext, com.example.weChatFriends.R.layout.item_friend, null); return view; 4.ListView设置适配器 代码: package fry; imp

  • Android中使用listview实现qq/微信好友列表

    首先附上运行结果: 如果你没有学过listview请你先看一看基本知识.不想再说的那么细了 太多了. 首先是listview布局 <?xml version="1.0" encoding="utf-8"?> <ListView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/lv_view" android

  • android 实现类似微信缓存和即时更新好友头像示例

    引言 使用微信时我们会发现,首次进入微信的好友列表时,会加载好友头像,但是再次进入时,就不用重新加载了,而且其他页面都不用重新加载,说明微信的好友头像是缓存在本地的,然后好友修改头像后,又会及时的更新,这个功能是如何实现的呢,我们来分析一下 分析 关于头像缓存的实现 头像是网络图片,而且数据量较大,如果用我们常用的SharedPreferences将头像以Bitmap的形式存储,势必会造成OOM,这个方法是行不通的,我们存储的只能是图片的地址,但是如果只存储地址的话,要转化成图片,还是要通过网络

  • Android实现类似微信的文本输入框 效果

    本文内容比较简单,给大家介绍一下微信的文本输入框是如何实现的,其实那只是个普通的文本框设了一个特殊的背景而已.具体微信怎么实现的,大家可以反编译下,这里介绍下如何实现这个背景. 可以先看下文章末尾的效果图,里面的文本框是不是和微信的比较像啊,下面说下实现思想: 首先,这种效果用.9图我不知道是否可以做出来.如果不用.9图的话,那就只能用drawable来写,这种drawable有点复杂,可以采用LayerList来实现,我的思想如下: 分三层实现,这里假设activity的背景是白色,第一层也(

  • Android实现屏蔽微信拉黑和删除联系人功能示例

    Android实现屏蔽微信拉黑和删除联系人功能,废话不多说,具体如下: 实现效果: 让微信永远弹不出那个删除的对话框不就相当于屏蔽掉该功能了吗?哈哈效果如图: 实现原理: 1.我们知道,其实微信每次删除联系人都会弹出此页面 2.如果你对AccessibilityService有过了解或者有看过我之前的两篇博客,你会知道,其实每次弹出这个框,都会触发AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED这个事件,所以我们只要在每次触发该事件的时候进行判断当前页面是

  • Android采用消息推送实现类似微信视频接听

    本文实例为大家分享了Android实现类似微信视频接听的具体代码,供大家参考,具体内容如下 1.背景需求:业务需要接入视频审核功能,在PC 端发起视频通话,移动端显示通话界面点击接听后进行1对1视频通话. 2.解决方案:因为项目没有IM功能.只集成了极光消息推送(极光消息推送接入参考官方文档,经过跟需求沟通,采用消息推送调起通话接听界面.再集成腾讯实时音视频SDK(具体集成方式参考官方文档).最终实现类似微信1对1通话功能. 3.技术实现: A:编写一个广播接收器,并且在 AndroidMani

  • Android 类似微信登录输入框效果

    微信的登录输入框效果如下 进入自动打开自动启动软键盘 点击下一个输入框,下划线颜色改变 怎么实现这样的效果呢,其实非常简单! 简单的布局我就不说了,直接上干货. 1.实现进入自动弹出软键盘,在根文件中的Activity中设置 windowSoftInputMode 属性为 stateVisible|adjustResize 例如 <activity android:name=".SetLoginPasswordActivity" android:windowSoftInputMo

  • Android计步模块实例代码(类似微信运动)

    最近在项目中研究计步模块,每天0点开始记录当天的步数,类似微信运动.碰到了不少坑今天有时间整理出来给大家看看. 做之前在google.baidu.github上搜了个遍没找到好的,大多数都是需要在后台存活,需要后台Service. 对于现在的各大手机厂商为了提高电池的续航里程(省电),基本上AlertManager. android.intent.action.BOOT_COMPLETED.后台Service都是被干掉的. 后台保活策略Service,基本上没什么用,被手机系统干掉只是时间问题,

  • Android实现类似qq微信消息悬浮窗通知功能

    实现方法:(需要开启悬浮窗通知权限.允许应用在其他应用上显示) 一.利用headsup 悬挂式Notification,他是5.0中新增的,也就是API中的Headsup的Notification,可以在不打断用户操作的时候,给用户通知 二.使用Window创建悬浮窗 当window属性设置为FLAGE_NOT_FOCUSABLE表示不需要获取焦点,也不需要接受各种输入事件,此标记会同时启用FLAGE_NOT_TOUCH_MODEL,最终事件会直接传递给下层具有焦点的Widow FLAGE_NO

  • Android基于ViewPager实现类似微信页面切换效果

    此文,仅做为个人学习Android,记录成长以及方便复习! 实现ViewPager实现类似微信的页面切换,此文通过Fragment适配器实现 首先在布局文件activity_main.xml添加ViewPager ViewPager是页面,PagerTabStrip和 PagerTitleStrip是设置标题的 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android=

  • Android 高仿微信朋友圈动态支持双击手势放大并滑动查看图片效果

    最近参与了开发一款旅行APP,其中包含实时聊天和动态评论功能,终于耗时几个月几个伙伴完成了,今天就小结一下至于实时聊天功能如果用户不多的情况可以scoket实现,如果用户万级就可以采用开源的smack + opnefile实现,也可以用mina开源+XMMP,至于怎么搭建和实现,估计目前github上一搜一大把,至于即时通讯怕误人子弟,暂且不做介绍,现就把实现的一个微信朋友圈的小功能介绍一下. 先上效果图: 一拿到主流的UI需求,大致分析下,需要我ListView嵌套Gridview,而grid

  • Android开发之微信底部菜单栏实现的几种方法汇总

     实现方式 实现的方式有很多种 这里总结最常见的几种方式,以后再添加其他的. viewPager + RadioGroup viewPager + FragmentTabHost viewpager +TabLayout viewPager+RadioGroup 感觉这是最简单的一个了,我也就不贴代码 说说我理解的思路吧 通过给pager 和RadioGroup 添加监听,监听两个控件的变化 实现联动 当viewPager的显示pager改变就会触发监听 ,在监听中选中对应的RadioButto

随机推荐