Android--图片的三级缓存策略
三级缓存
缓存(内存)--->本地磁盘---->网络 1、首先看一下图片存储到本地磁盘
public class FileUtils {
String path;//文件存储的地方
public FileUtils(Context context,String dirName){//文件夹的名称
if(Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED){//SD卡就绪
//文件可以放在SD卡中
path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/"+dirName;
}else{
//文件放在内部存储器里
path = context.getCacheDir().getAbsolutePath()+"/"+dirName;
}
new File(path).mkdirs();
}
//读取和写入
public void saveToSDCard(String key, Bitmap bmp){
FileOutputStream fos = null;
try {
fos = new FileOutputStream(new File(path,key));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
//保存固定格式图片,不压缩
bmp.compress(Bitmap.CompressFormat.PNG,100,fos);
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//读取
public Bitmap readFromSDCard(String key){
return BitmapFactory.decodeFile(new File(path,key).getAbsolutePath());
}
}
FileUtils.java
2、图片加载,先加载缓存图片,缓存没有再到本地加载,本地没有再到网络加载
public class ImageLoader {
/**
* 缓存类
* LruCache原理:Cache保存一个强引用来限制内容数量。每当Item被访问的时候,此Item就会移动到队列的头部。
* 当cache已满的时候加入新的item时,在队列尾部的item会被回收。
* 解释:当超出指定内存值则移除最近最少用的图片内存
*/
private static LruCache<String,Bitmap> cache;
private FileUtils fileUtils;
//使用线程池
ExecutorService threadLooper;
public ImageLoader(Context context,String dirName){
//获取系统分配的最大内存
cache = new LruCache<String,Bitmap>((int) (Runtime.getRuntime().maxMemory()/8)){
//判断每一个键对应得值得大小
//自动释放使用频率低的文件
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();//也可以value.getWidth()*value.getHeight()
}
};
fileUtils = new FileUtils(context,dirName);
threadLooper = Executors.newFixedThreadPool(5);
}
//存储到缓存
private void saveToCache(String key, Bitmap bmp){
cache.put(key,bmp);
}
//从缓存中读取
private Bitmap readFromCache(String key){
return cache.get(key);
}
public void loadImage(final String url, @NonNull final ImageLoadListener listener){
final String key = url.replaceAll("[\\W]","");//非单次类型用空替换
//第一级,缓存
if(readFromCache(key)!=null){
//缓存已存在,直接拿出来,但是,不是直接返回,因为后面还有请求网络,并不能确定什么时候返回。这里使用回调
listener.loadImageFinish(readFromCache(key));
Log.e("TAG","从缓存中加载");
}else {
//第二级,本地磁盘
Bitmap bitmap = fileUtils.readFromSDCard(key);
if(bitmap!=null){
//存储到缓存
saveToCache(key,bitmap);
//返回
listener.loadImageFinish(fileUtils.readFromSDCard(key));
Log.e("TAG","从SDCard中加载");
}else{
Log.e("TAG","从网络下载");
final Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
listener.loadImageFinish((Bitmap) msg.obj);
}
};
//下载,使用线程池
threadLooper.execute(new Runnable() {
@Override
public void run() {
//开始下载,子线程
try {
Bitmap bitmap1 = BitmapFactory.decodeStream(new URL(url).openStream());
//保存到本地,保存到缓存
fileUtils.saveToSDCard(key,bitmap1);
saveToCache(key,bitmap1);
//使用异步任务通知主线程修改UI
Message msg = handler.obtainMessage();
msg.obj = bitmap1;
handler.sendMessage(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
}
}
public void cancelDowload(){
threadLooper.shutdown();
}
public interface ImageLoadListener{
void loadImageFinish(Bitmap bitmap);
}
}
ImageLoader.java
3、NetworkImageView自定义View,继承自ImageView
res/values/创建network_attrs.xml
<resources>
<declare-styleable name="NetworkImageView">
<attr name="url" format="string"/>
</declare-styleable>
</resources>
network_attrs.xml
public class NetworkImageView extends ImageView{
String url;
ImageLoader loader;
public NetworkImageView(Context context) {
super(context);
}
public NetworkImageView(Context context, AttributeSet attrs) {
super(context, attrs);
//获取自定义属性
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.NetworkImageView);
url = a.getString(R.styleable.NetworkImageView_url);
a.recycle();
loader = new ImageLoader(context,"network");
if(url!=null){
setUrl(url);
}
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
//设置到图片上去
loader.loadImage(url, new ImageLoader.ImageLoadListener() {
@Override
public void loadImageFinish(Bitmap bitmap) {
setImageBitmap(bitmap);
}
});
}
}
NetworkImageView.java
4、测试
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.example.lesson19_threecache.MainActivity"> <Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="start"
android:text="加载图片" /> <ImageView
android:id="@+id/iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher" /> <com.example.mylibrary.widget.NetworkImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:url="http://ent.chinadaily.com.cn/img/site1/20161117/448a5bd66b8519976e9933.jpeg"/>
</LinearLayout>
activity_main.xml
public class MainActivity extends AppCompatActivity {
ImageView iv;
ImageLoader loader;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iv = (ImageView) findViewById(R.id.iv);
loader = new ImageLoader(this,"three_cache");
}
public void start(View v){
loader.loadImage("http://image.cqcb.com/d/file/personage/2016-11-17/9b05cf89592d3e3eb2027519fbb98214.jpg", new ImageLoader.ImageLoadListener() {
@Override
public void loadImageFinish(Bitmap bitmap) {
iv.setImageBitmap(bitmap);
}
});
}
MainActivity.java
Android--图片的三级缓存策略的更多相关文章
- Android中图片的三级缓存策略
在开发过程中,经常会碰到进行请求大量的网络图片的样例.假设处理的不好.非常easy造成oom.对于避免oom的方法,无非就是进行图片的压缩.及时的回收不用的图片.这些看似简单可是处理起来事实上涉及的知 ...
- Android Volley框架的使用(四)图片的三级缓存策略(内存LruCache+磁盘DiskLruCache+网络Volley)
在开发安卓应用中避免不了要使用到网络图片,获取网络图片很简单,但是需要付出一定的代价——流量.对于少数的图片而言问题不大,但如果手机应用中包含大量的图片,这势必会耗费用户的一定流量,如果我们不加以处理 ...
- 安卓开发笔记——关于图片的三级缓存策略(内存LruCache+磁盘DiskLruCache+网络Volley)
在开发安卓应用中避免不了要使用到网络图片,获取网络图片很简单,但是需要付出一定的代价——流量.对于少数的图片而言问题不大,但如果手机应用中包含大量的图片,这势必会耗费用户的一定流量,如果我们不加以处理 ...
- Android中图片的三级缓存
为什么要使用三级缓存 如今的 Android App 经常会需要网络交互,通过网络获取图片是再正常不过的事了 假如每次启动的时候都从网络拉取图片的话,势必会消耗很多流量.在当前的状况下,对于非wifi ...
- android中图片的三级缓存cache策略(内存/文件/网络)
实现图片缓存也不难,需要有相应的cache策略.这里我采用 内存-文件-网络 三层cache机制,其中内存缓存包括强引用缓存和软引用缓存(SoftReference),其实网络不算cache,这里姑且 ...
- 简单地Android中图片的三级缓存机制
我们不能每次加载图片的时候都让用户从网络上下载,这样不仅浪费流量又会影响用户体验,所以Android中引入了图片的缓存这一操作机制. 原理: 首先根据图片的网络地址在网络上下载图片,将图片先缓存到内存 ...
- 关于Android中的三级缓存
三级缓存的提出就是为了提升用户体验.当我们第一次打开应用获取图片时,先到网络去下载图片,然后依次存入内存缓存,磁盘缓存,当我们再一次需要用到刚才下载的这张图片时,就不需要再重复的到网络上去下载,直接可 ...
- Android图片下载以及缓存框架
实际开发中进行图片下载以及缓存的框架 介绍一下开发中常见图片加载框架的使用和对比一下优缺点. 1.Picasso 框架 在Android中开发,常需要从远程获取图片并显示在客户端,当然我们可以使用原生 ...
- 【Java/Android性能优 6】Android 图片SD卡缓存 使用简单 支持预取 支持多种缓存算法 支持不同网络类型 支持序列化
本文转自:http://www.trinea.cn/android/android-imagesdcardcache/ 本文主要介绍一个支持图片自动预取.支持多种缓存算法.支持数据保存和恢复的图片Sd ...
随机推荐
- 简明Vim练级攻略
原文:酷壳网 vim的学习曲线相当的大(参看各种文本编辑器的学习曲线),所以,如果你一开始看到的是一大堆VIM的命令分类,你一定会对这个编辑器失去兴趣的.下面的文章翻译自<Learn Vim P ...
- 关于使用iframe标签自适应高度的使用
在ifrome内设定最小高度,(此方法只适用于页面内切换高度不一.但是会保留最大高度,返回后保持最大高度不再回到最初页面的高度) <iframe id="one4" widt ...
- for语句嵌套使用 实现9*9乘法表
这个实例主要考察对for循环语句的使用,出现递增规律的乘法表. 开发环境 开发工具:Microsoft Visual Studio2010 旗舰版 具体步骤 先是制作一个 ...
- SQL Server Analysis Services 数据挖掘(1)
来源: http://technet.microsoft.com/zh-cn/library/dn633476.aspx 假如你有一个购物类的网站,那么你如何给你的客户来推荐产品呢?这个功能在很多 电 ...
- JQUERY1.9学习笔记 之可见性过滤器(二) 可见选择器
描述:选择所有可见的元素. 例:点击时让所有的可见的div元素变黄. <!doctype html><html lang="en"> <head> ...
- Java环境配置出现的问题及解决办法
我使用的安装文件,从博客园一个童鞋那里找到的,连接是http://www.cnblogs.com/SelectError/p/3205582.html#commentform 开发基础环境,版本为Ja ...
- ubuntu各版本的区别
ubuntu.kubuntu以及xubuntu的区别Ubuntu默认是Gnome:KUbuntu用的是KDE,效果比较炫目,但是系统要求也较高XUbuntu用的是Xface,比较轻量,系统要求较低,推 ...
- Solr4.8.0源码分析(20)之SolrCloud的Recovery策略(一)
Solr4.8.0源码分析(20)之SolrCloud的Recovery策略(一) 题记: 我们在使用SolrCloud中会经常发现会有备份的shard出现状态Recoverying,这就表明Solr ...
- Unity3D RPC调用顺序问题
使用Unity自带的Network实现多人协同任务时,因为使用RPC传递消息.RPC即远程过程调用,对于它的使用,第一反应的问题就是如果连续两次调用RPC,RPC的函数会顺序执行吗?还是只要RPC的消 ...
- BZOJ 1027 合金
Description 某公司加工一种由铁.铝.锡组成的合金.他们的工作很简单.首先进口一些铁铝锡合金原材料,不同种类的原材料中铁铝锡的比重不同.然后,将每种原材料取出一定量,经过融解.混合,得到新的 ...