KJFrameForAndroid框架项目地址:https://github.com/kymjs/KJFrameForAndroid

或备用地址http://git.oschina.net/kymjs/KJFrameForAndroid

KJFrameForAndroid开发群:257053751

我们都知道,计算机读取数据时:内存的读取速度是最快的,然后是文件的读取速度,最后是网络资源的读取。

假设每次载入同一张图片都要从网络获取,那代价实在太大了。所以同一张图片仅仅要从网络获取一次就够了,然后在本地缓存起来,之后载入同一张图片时就 从缓存中载入就能够了。从内存缓存读取图片是最快的,可是由于Android对每一个应用所能使用的内存容量都有限制,所以最好再加上文件缓存。文件缓存空间也不是无限大的,容量越大读取效率越低,这个非常好理解,从沙漠中找出丢失的一根针和从盘子中找到一根针,哪个easy一想即知。因此我们常设置一个限定大小比方10M。

所以,载入图片的流程应该是:

    1、先从内存缓存中获取,取到则返回,取不到则进行下一步;

    2、从文件缓存中获取,取到则返回并更新到内存缓存,取不到则进行下一步;

    3、从网络下载图片,并更新到内存缓存和文件缓存。

假设您仅仅想了解文件缓存与内存缓存公用,请查看下一篇博文。


在过去,我们常常会使用一种很流行的内存缓存技术的实现,即软引用或弱引用 (SoftReference or WeakReference)。可是依据Google的描写叙述:如今已经不再推荐使用这样的方式了,由于从 Android 2.3 (API Level 9)開始,垃圾回收器会更倾向于回收持有软引用或弱引用的对象,这让软引用和弱引用变得不再可靠。另外,Android 3.0 (API Level 11)中,图片的数据会存储在本地的内存其中,因而无法用一种可预见的方式将其释放,这就有潜在的风险造成应用程序的内存溢出并崩溃。

因此,我们很多其它的是去使用lru算法(Least Recently Used 最近最少使用算法)最初这样的算法是用在操作系统调度上的。他的原理是通过个线性表存储数据,并记录数据每次调用次数,越经常使用到的排名就越靠前,越少用到的排名就越靠后,假设是一个新增加的数据,就会把它放在第一位,然后移除掉排名最后一位的数据。这里是KJFrameForAndroid框架中关于内存lru算法的实现方式LruMemoryCache



既然是载入网络图片,那么当然须要载入的控件和网络图片地址作为參数,示比例如以下所看到的

private void loadImage(ImageView imageView, String imageUrl) {
// 首先訪问内存缓存,推断图片是否已经存在
Bitmap bitmap = mMemoryCache.get(StringUtils.md5(imageUrl));
if (bitmap != null) {
imageView.setImageBitmap(bitmap);
}else{
//否则就去网络下载
BitmapWorkerTask task = new BitmapWorkerTask(imageView);
task.execute(imageUrl);
}
}

至于实际下载的方法,我就不具体解说了,相信大家都能想到,就是一个网络请求,然后下载图片,再转成bitmap,最后设置为控件图片。然而这里有一个须要注意的重要地方,就是当我们把图片下载成功后要记得在mMemoryCache中缓存起来。

这里是KJFraemForAndroid应用开发框架中的一段网络图片载入的代码:

  /********************* 异步获取Bitmap并设置image的任务类 *********************/
private class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
private View imageView; public BitmapWorkerTask(View imageview) {
this.imageView = imageview;
} @Override
protected Bitmap doInBackground(String... params) {
Bitmap bitmap = null;
//有关这种方法,以下的文章将会解说
  byte[] res = downloader.loadImage(params[0]);
if (res != null) {
bitmap = BitmapCreate.bitmapFromByteArray(res, 0, res.length,
config.width, config.height);
}
if (bitmap != null && config.openMemoryCache) {
// 图片加载完毕后缓存到LrcCache中
putBitmapToMemory(params[0], bitmap);
if (config.isDEBUG)
KJLoger.debugLog(getClass().getName(),
"put to memory cache\n" + params[0]);
}
return bitmap;
} @Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
if (imageView instanceof ImageView) {
if (bitmap != null) {
((ImageView) imageView).setImageBitmap(bitmap);
}
} else {
imageView.setBackgroundDrawable(new BitmapDrawable(bitmap));
}
if (config.callBack != null)
config.callBack.imgLoadSuccess(imageView);
taskCollection.remove(this);
}
}


深入理解图片载入在实际项目中的应用

以上仅仅是网络图片载入并缓存的基本操作,那么我们假设在实际项目中使用必须考虑到代码的完备性与可扩展性。

①比方我们想指定图片的大小,尽管我们能够通过设置view的固定宽高来强制图片的显示大小,但假设是一张几兆的图片,而我们仅仅须要15*15分辨率大小的显示区域,这显然是浪费的;

②又比方,我们希望控件在网络正在下载图片时先显示一个默认的图片(比方一个灰色的头像)又或者是图片下载的时候显示一个环形的进度条,那么上面的代码是没有办法的;

③再比方,我们希望图片的下载方式有多种,对于不同站点来源有不同的下载方式。。。。

这些种种特殊的需求告诉我们,上面的代码全然没有办法做到。那么为了控件的完备性与可扩展性,我们就须要一个配置器、一个显示器、一个下载器。。等等依据特殊须要而加入的插件式开发。

因此,我们能够看到在KJFrameForAndroid框架的org.kymjs.aframe.bitmap包下有着KJBitmapConfig、I_ImageLoder、I_Display等等用final修饰的类或者协议接口。

比方KJBitmapConfig类,是一个用final修饰的配置器类,通过这个配置器,我们就能够动态的对每一张下载的图片设置宽高、以及内存大小等。而I_ImageLoder、I_Display则是两个协议接口,分别定义了下载器和显示器的方法,这里实际上是GoF设计模式中工厂方法模式的应用,仅仅是这里的工厂实际上并非用来创建对象,而是用来定义显示方法或下载方法的,不论是哪个实现了I_ImageLoder抽象工厂的实际工厂,都必须有一个载入图片的方法。那么在项目的实际应用中,就能够无论这个下载器的实际工厂是什么,仅仅须要调用工厂的载入图片的方法即可了。

/**
* 图片加载接口协议,可自己定义实现此协议的下载器
*
* @explain 採用工厂方法模式设计的下载器,本类也是一个抽象工厂类,用于生产byte[]产品
* @author kymjs(kymjs123@gmail.com)
* @version 1.0
* @created 2014-7-11
*/
public interface I_ImageLoder {
public byte[] loadImage(String imageUrl); }

这里我们应该就能够知道上面的代码段中有这么一段代码原因了

byte[] res = downloader.loadImage(params[0]);

downloader实际上就是下载器的抽象工厂。



至于显示器的逻辑和下载器是一样的,这里我就不具体介绍了,大家能够自己查看KJFrameForAndroid的源码或演示样例项目。

这里是I_ImageLoader下载器协议的一个实现类 Downloader.java,大家当然也能够依据自己的须要去实现自己的下载器,这全然没有不论什么作为扩展试开发,这对于图片设置代码本身没有不论什么影响。

KJFrameForAndroid框架学习----高效设置网络图片的更多相关文章

  1. 02 uni-app框架学习:设置全局样式统一每个页面的背景颜色

    1.设置全局样式可以在App.vue里面 2.在每个页面的根view 里添加一个class名叫page

  2. Hadoop学习笔记—18.Sqoop框架学习

    一.Sqoop基础:连接关系型数据库与Hadoop的桥梁 1.1 Sqoop的基本概念 Hadoop正成为企业用于大数据分析的最热门选择,但想将你的数据移植过去并不容易.Apache Sqoop正在加 ...

  3. IdentityServer4 ASP.NET Core的OpenID Connect OAuth 2.0框架学习保护API

    IdentityServer4 ASP.NET Core的OpenID Connect OAuth 2.0框架学习之保护API. 使用IdentityServer4 来实现使用客户端凭据保护ASP.N ...

  4. EF框架学习手记

    转载: [ASP.NET MVC]: - EF框架学习手记 1.EF(Entity Framework)实体框架EF是ADO.NET中的一组支持开发面向数据的软件应用程序的技术,是微软的一个ORM框架 ...

  5. 2013 最新的 play web framework 版本 1.2.3 框架学习文档整理

    Play framework框架学习文档 Play framework框架学习文档 1 一.什么是Playframework 3 二.playframework框架的优点 4 三.Play Frame ...

  6. 各种demo——CI框架学习

    各种demo——CI框架学习   寒假学习一下CI框架,请各位多多指教! 一.CI的HelloWorld! 注意:CI禁止直接通过文件目录来访问控制器. ./application/controlle ...

  7. phalcon(费尔康)框架学习笔记

    phalcon(费尔康)框架学习笔记 http://www.qixing318.com/article/phalcon-framework-to-study-notes.html 目录结构   pha ...

  8. Yii框架学习笔记(二)将html前端模板整合到框架中

    选择Yii 2.0版本框架的7个理由 http://blog.chedushi.com/archives/8988 刚接触Yii谈一下对Yii框架的看法和感受 http://bbs.csdn.net/ ...

  9. Hadoop Streaming框架学习2

    Hadoop Streaming框架学习(二) 1.常用Streaming命令介绍 使用下面的命令运行Streaming MapReduce程序: 1: $HADOOP_HOME/bin/hadoop ...

随机推荐

  1. node.js NPM 使用

    n=NPM是一个Node包管理和分发工具,已经成为了非官方的发布Node模块(包)的标准.有了NPM,可以很快的找到特定服务要使用的包,进行下载.安装以及管理已经安装的包.npms安装: 下载npm源 ...

  2. php date操作

    date(format,timestamp) d - 月中的天 (01-31) m - 当前月,以数字计 (01-12) Y - 当前的年(四位数) h 小时,12 小时格式,有前导零 01 到 12 ...

  3. java的深复制与浅复制

    今天座右铭-----浪费时间就等于慢性自杀 ⑴浅复制(浅克隆) 被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原 来的对象.换言之,浅复制仅仅复制所考虑的对象,而不复 ...

  4. linux学习之(四)-用户、组的操作,给文件文件夹设置组,更改目录权限、文件权限

    命令帮助查看: man 命令(查看一个命令的详细帮助信息) 例:man useradd 或者用  -h   格式   命令 -h(查看一个命令的简要帮助) 例:useradd -h 用户: 在user ...

  5. office中回车符的问题

    导入数据,有时直接把execl中的数据复制到数据表中,但如果有回车符时就会出错,这时可以用: Alt+1+0三个键来代表回车,直接替换掉

  6. jboss清楚缓存

    在服务器上部署或更新时,常常会忘记删除JBOSS的缓存.忘记删除缓存的后果,经常就是改好了代码却还是原来的错误,然后查找半天,浪费时间.所以在重新部署JBOSS,在启动JBOSS前一定要删除JBOSS ...

  7. EC读书笔记系列之13:条款25 考虑写出一个不抛异常的swap函数

    记住: ★当std::swap对你的类型效率不高时,提供一个swap成员函数,并确定其不抛出异常 ★若你提供一个member swap,也该提供一个non-member swap来调用前者.对于cla ...

  8. stat 函数讲解

    表头文件:    #include <sys/stat.h>                     #include <unistd.h>定义函数:    int stat( ...

  9. “-="的陷阱

    1.有如下代码(显示下拉框时,屏幕最大化右键菜单的显示坐标处理): 起初: Rectangle rect = System.Windows.Forms.SystemInformation.Virtua ...

  10. [重写库函数]atoi

    算法分析 1. 若字符串开头是空格,则跳过所有空格,到第一个非空格字符,如果没有,则返回0. 2. 若第一个非空格字符是符号+/-,则标记isPositive的真假,这道题还有个局限性,那就是在c++ ...