android读取大图片并缓存
UI组件方面采用Gallery+ImageSwitcher组合,这里略过,详情参见google Android API。相册图片预取缓存策略是内存缓存(硬引用LruCache、软引用SoftReference<Bitmap>)、外部文件缓存(context.getCachedDir()),缓存中取不到的情况下再向服务端请求下载图片。同时缓存三张图片(当前预览的这张,前一张以及后一张)。1.内存缓存//需要导入外部jar文件 android-support-v4.jar
import android.support.v4.util.LruCache;
//开辟8M硬缓存空间
private final int hardCachedSize = 8*1024*1024;
//hard cache
private final LruCache<String, Bitmap> sHardBitmapCache = new LruCache<String, Bitmap>(hardCachedSize){
@Override
public int sizeOf(String key, Bitmap value){
return value.getRowBytes() * value.getHeight();
}
@Override
protected void entryRemoved(boolean evicted, String key, Bitmap oldValue, Bitmap newValue){
Log.v("tag", "hard cache is full , push to soft cache");
//硬引用缓存区满,将一个最不经常使用的oldvalue推入到软引用缓存区
sSoftBitmapCahe.put(key, new SoftReference<Bitmap>(oldValue));
}
}
//软引用
private static final int SOFT_CACHE_CAPACITY = 40;
private final static LinkedHashMap<String, SoftReference<Bitmap>> sSoftBitmapCache =
new LinkedHashMao<String, SoftReference<Bitmap>>(SOFT_CACHE_CAPACITY, 0.75f, true){
@Override
public SoftReference<Bitmap> put(String key, SoftReference<Bitmap> value){
return super.input(key, value);
}
@Override
protected boolean removeEldestEntry(LinkedHashMap.Entry<Stirng, SoftReference<Bitmap>> eldest){
if(size() > SOFT_CACHE_CAPACITY){
Log.v("tag", "Soft Reference limit , purge one");
return true;
}
return false;
}
}
//缓存bitmap
public boolean putBitmap(String key, Bitmap bitmap){
if(bitmap != null){
synchronized(sHardBitmapCache){
sHardBitmapCache.put(key, bitmap);
}
return true;
}
return false;
}
//从缓存中获取bitmap
public Bitmap getBitmap(String key){
synchronized(sHardBitmapCache){
final Bitmap bitmap = sHardBitmapCache.get(key);
if(bitmap != null)
return bitmap;
}
//硬引用缓存区间中读取失败,从软引用缓存区间读取
synchronized(sSoftBitmapCache){
SoftReference<Bitmap> bitmapReference = sSoftBtimapCache.get(key);
if(bitmapReference != null){
final Bitmap bitmap2 = bitmapReference.get();
if(bitmap2 != null)
return bitmap2;
else{
Log.v("tag", "soft reference 已经被回收");
sSoftBitmapCache.remove(key);
}
}
}
return null;
}2.外部文件缓存private File mCacheDir = context.getCacheDir();
private static final int MAX_CACHE_SIZE = 20 * 1024 * 1024; //20M
private final LruCache<String, Long> sFileCache = new LruCache<String, Long>(MAX_CACHE_SIZE){
@Override
public int sizeOf(String key, Long value){
return value.intValue();
}
@Override
protected void entryRemoved(boolean evicted, String key, Long oldValue, Long newValue){
File file = getFile(key);
if(file != null)
file.delete();
}
}
private File getFile(String fileName) throws FileNotFoundException {
File file = new File(mCacheDir, fileName);
if(!file.exists() || !file.isFile())
throw new FileNotFoundException("文件不存在或有同名文件夹");
return file;
}
//缓存bitmap到外部存储
public boolean putBitmap(String key, Bitmap bitmap){
File file = getFile(key);
if(file != null){
Log.v("tag", "文件已经存在");
return true;
}
FileOutputStream fos = getOutputStream(key);
boolean saved = bitmap.compress(CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
if(saved){
synchronized(sFileCache){
sFileCache.put(key, getFile(key).length());
}
return true;
}
return false;
}
//根据key获取OutputStream
private FileOutputStream getOutputStream(String key){
if(mCacheDir == null)
return null;
FileOutputStream fos = new FileOutputStream(mCacheDir.getAbsolutePath() + File.separator + key);
return fos;
}
//获取bitmap
private static BitmapFactory.Options sBitmapOptions;
static {
sBitmapOptions = new BitmapFactory.Options();
sBitmapOptions.inPurgeable=true; //bitmap can be purged to disk
}
public Bitmap getBitmap(String key){
File bitmapFile = getFile(key);
if(bitmapFile != null){
Bitmap bitmap = BitmapFactory.decodeStream(new FileInputStream(bitmapFile), null, sBitmapOptions);
if(bitmap != null){
//重新将其缓存至硬引用中
...
}
}
}3.从服务端下载图片private static String generateKey(String fileId, int width, int height) {
String ret = fileId + "_" + Integer.toString(width) + "x" + Integer.toString(height);
return ret;
}
String key = generateKey(...)即可生成唯一的key值下载成功后调用1内存缓存的putBitmap()函数,缓存图片。在外部文件缓存中也写入一份,调用2的putBitmap()函数.4.预览图片的流程1) 如果预览的图片在内存缓存区中,直接调用1的getBitmap()函数,获取bitmap数据(先在硬引用缓存区查找匹配,若硬引用区匹配失败,再去软引用区匹配)2) 如果从内存缓存区读取失败,再从外部文件缓存中读取,调用2的getBitmap()函数3) 如果从外部文件缓存中读取失败,则从服务端下载该图片,过程3.5.生成key值
相关文章:

[ZJOI2018]历史
Description: 给定一棵树,定义每个点的操作为把这个点到1号点的路径覆盖上颜色i,每次该点到1号点经过的不同颜色段数会加到答案中,要使所有点按某一顺序操作完后答案最大 给定每个点要执行的操作次数,并给出m次修改,问每次修改后的最大答案 Hint: \(n,m \le 4*10^5\) Solution:…

C++ STL: lower_bound 和 upper_bound
接口声明 以下有两个不同的版本 lower_bound template <class ForwardIterator, class T>ForwardIterator lower_bound (ForwardIterator first, ForwardIterator last,const T& val);template <class ForwardIterator, class T, class Compare>ForwardItera…

1199: 房间安排
1199: 房间安排 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 1 Solved: 1[Submit][Status][Web Board]Description 2010年上海世界博览会(Expo2010),是第41届世界博览会。于2010年5月1日至10月31日期间,在中国上海市举行。本次世博会也是由中国举办的首届世界…

oracle判断非空并拼接,oracle sql 判断字段非空,数据不重复,插入多跳数据
oracle sql 判断字段非空,数据不重复select distinct(mobile) from wx_user_mobile where active_time is not nullbegininsert into sms_submit(id,gateway_id,source_number,dest_number,message_content)values(sms_system.nextval,1,88…

量产工具介绍(2)
前面介绍了量产工具概念,U盘构造,量产工具获取途径,以及国内的芯片分类,今天,我们从注意事项及常见问题继续介绍量产相关知识注意事项厂家推出的量产工具也是在不断提高版本的,新版本添加有新主控型号驱动。…

C++ STL: 容器vector源码分析
文章目录前言vector的核心接口vector push_back实现vector 的 Allocatorvector 的 push_back总结前言 vector 是我们CSTL中经常使用的一个容器,提供容量可以动态增长,并且随机访问内部元素的数据存储功能。 这个容器我们最常使用,所以也是最…

STM32学习笔记9(SysTick滴答时钟)
我不得不说意法半导体确实有点风骚!甚至有点变态。我对ST文档 STM32F10XXX参考手册的编辑水平真是不敢恭维。手册中好多说明都是含糊不清,甚至将好多对初学者来说很重要的地方都一笔带过,让人着实摸不着头脑。比如前面我说过的关于NVIC嵌套向…

oracle存储空间管理,Oracle存储空间管理
Oracle存储空间管理1.查看每个数据文件的剩余表空间(一个表空间只对应N个数据文件,N一般等于1)主要是利用表dba_free_space(表空间剩余空间状况)和dba_data_files(数据文件空间占用情况)select b.file_id "文件ID",b.tablespace_name "表空间名",b.f…

漫谈Httpclient
引用地址: http://hc.apache.org/httpclient-3.x/ End of life The Commons HttpClient project is now end of life, and is no longer being developed. It has been replaced by the Apache HttpComponents project in its HttpClient andHttpCore modules, whic…

具体数学-扰动法
from scipy.special import combn int (input("n: "))k int (input("k: "))sum1 0for j in range(0, k):for i in range(0, n1):sum1 sum1 (i**j)*comb(k1,j)result ((n1)**(k1) - sum1)/comb(k1,k) print(result) python 中计算排列组合:…

C++ STL: 超详细 容器 deque 以及 适配器queue 和 stack 源码分析
文章目录前言deque 实现deque类_Deque_iterator 类deque 的元素插入 insert函数deque如何模拟空间连续queue 实现stack 的实现前言 C容器中 deque是一个非常有趣的容器结构,我们知道deque本身是一个支持双向扩容的结构,对外表现出连续的存储方式。 本节将…

php好的mvc中index方法,创建一个mvc应用目录架构并创建入口文件index.php
摘要:<?php require vendor/autoload.php;require pig/Base.php;define(ROOT_PATH,__DIR__./);$configrequire pig/config.php;$queryStr$_S<?php require vendor/autoload.php;require pig/Base.php;define(ROOT_PATH,__DIR__./);$configrequire pig/confi…

C语言对mysql数据库的操作
C语言对mysql数据库的操作 原文:C语言对mysql数据库的操作这已经是一相当老的话题。不过今天我才首次使用,把今天的一些体会写下来,也许能给一些新手带来一定的帮助,更重要的是供自己今后忘记的怎么使用而进行查阅的! 我们言归正传…

[转]MCC(移动国家码)和 MNC(移动网络码)
From : http://blog.chinaunix.net/uid-20484604-id-1941290.html 国际移动用户识别码(IMSI) international mobile subscriber identity 国际上为唯一识别一个移动用户所分配的号码。 从技术上讲,IMSI可以彻底解决国际漫游问题。但是由于…

虚拟机cenos 重置密码
许久不用虚拟机,临时想登录看下,结果想不起来密码了,尝试各种可能的密码都登录失败。然后百度查验各种方法,看到一篇文章然后根据上面说的成功解决了问题,贴出链接:https://blog.csdn.net/dannistang/artic…

g-git 相关命令 及其 基本原理探索 (一)
文章目录git 最小配置作用域git 创建本地仓库git log 查看版本演进.git 目录refs目录objectsgit 三种对象类型详解 (commit ,tree,blob)因为工作需求,接下来将从git的使用到其内部工作原理,来避免代码提交或者review或者版本管理上的一些尴尬,…

php表单退出怎么写,PHP提交表单失败后如何保留填写的信息
[导读]本文章来给各位同学介绍PHP提交表单失败后如何保留填写的信息一些方法总结,最常用的就是使用缓存方式了,这种方法如果网速慢是可能出问题的,最好的办法就是使用ajax了。1.使用header头设置缓存控制头Cache-c本文章来给各位同…

lists,tuples and sets of Python
(python2.7.x) Lists 列表 列表是一个有序序列(集合),可变的(可以修改),可以理解为其他语言中的数组类型,但是列表更灵活更强大。 列表由方括号[]来定义的,它的元素可以是任意类型或对象,一个列…

Javascript中使用WScript.Shell对象执行.bat文件和cmd命令
WScript.Shell(Windows Script Host Runtime Library)是一个对象,对应的文件是C:/WINDOWS/system32/wshom.ocx,Wscript.shell是服务器系统会用到的一种组件。shell 就是“壳”的意思,这个对象可以执行操作系统外壳常用…

控件绘制的方法
1处理WM_PAINT 最极端的选择是执行一个 WM_PAINT 处理程序,并且自己完成所有的绘制。这意味着,您的代码将需要进行一些与呈现控件相关的琐事 — 创建适当的设备上下文(一个或多个),决定控件的大小和位置,绘…

google gflags的参数解析,便捷实用
命令行参数解析,一直是我们后段开发人员需要经常使用的一个功能,用来从终端解析接口的输入 ,并做出对应的处理。这里为使用C/python的开发人员推荐一个便捷的命令行解析接口集 gflags。 我们之前使用C的getopt/getopt_long 函数需要自己使用…

linux进程下的线程数,Linux下查看进程线程数的方法
0x01:ps -ef只打印进程,而ps -eLf会打印所有的线程[rootcentos6 ~]# ps -ef | grep rsyslogdroot 1470 1 0 2011 ? 00:01:13 /sbin/rsyslogd -c 4root 29865 28596 0 22:45 pts/5 00:00:00 grep rsyslogd[rootcentos6 ~]# ps…

OpenCV学习(20) grabcut分割算法
在OpenCV中,实现了grabcut分割算法,该算法可以方便的分割出前景图像,操作简单,而且分割的效果很好。算法的原理参见papaer:“GrabCut” — Interactive Foreground Extraction using Iterated Graph Cuts 比如下面的一…

VMware workstation中rhel安装VMware tools失败
切换登录用户为root即可转载于:https://www.cnblogs.com/dazzleC/p/10555809.html

g-git 相关命令 及其 基本原理探索(二):git 在工作中的常用命令操作 ,超级实用!!!
上一篇git 基本原理对git的使用以及文件分布已经有了一个整体的了解。 本篇将对工作中常用的一些git 操作命令的操作进行总结归纳,方便今后查阅。 文章目录1. 分离头指针2. 通过HEAD 来进行不同提交的差异对比3. 删除不需要的分支4. 对当前分支最近一次提交的messag…

Linux中的文件寻址,Linux文件寻址算法:逻辑地址到物理地址的转换
题目描述:编写一个函数实现Linux文件寻址的算法,即读取文件当前位置到物理存储位置的转换函数,需要给出运行的测试数据,可以假设和模拟需要的数据和结构。即编写一个函数unsigned long ltop(unsigned long logblkNum). 计算逻辑块…

datatable和dataset的区别
DataSet 是离线的数据源 DataTable 是数据源中的表.当然也可以自己建一张虚表。插入数据库中 DataSet是DataTable的容器DataSet可以比作一个内存中的数据库,DataTable是一个内存中的数据表,DataSet里可以存储多个DataTabledatatable是dataset中的一个表另…

如何避免重构带来的危险
http://blog.jobbole.com/30049/ 重构代码很危险,它会给测试工作增加巨大的负担。除非你的程序需要重构,一定不要轻易重构代码。我这里所说的并不是把一个for循环改成while循环,或把一个StringBuffer改成StringBuilder,我说的是大…

ip通信(第二周)
计算机网络分为局域网(LAN)、城域网(MAN)和广域网(WAN)。拓扑结构分为星型网,树形网,分布式网络,总线型网络,环型网络和复合型网络。认识了几个常见的国际标准…

《DDIA》读书笔记
数据存储系统的经典书籍: 从数据系统的特性开始,先讲单机存储引擎 再到 分布式存储系统,最后到一些数据流的处理方式,作者深入浅出,译者更是精雕细琢,本书需要细品。 将持续阅读整理,先从理论走…