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 ...
随机推荐
- 【POJ2912】【并查集】Rochambeau
Description N children are playing Rochambeau (scissors-rock-cloth) game with you. One of them is th ...
- kafka监控
做kafka相关项目,需要用到监控的东东,找到了两个方法 第一个: http://quantifind.com/KafkaOffsetMonitor/ 非常容易上手,效果也直观,可以显示各个topic ...
- Java学习----对象与对象之间的关系
1.依赖 对象之间最弱的一种关联方式,是临时性的关联.代码中一般指由局部变量,函数参数,返回值建立的对于其他对象的调用关系. public class A { // 方法一 public void t ...
- Android安装 sdk+jdk+Eclipse+Adt开发工具
根据别人提供的手册和安装过程体验加以更新和详细描述 安装Android开发工具 开发Android应用程序的门坎并不高,因为Google已经为Android应用程序开发提供了免费而且跨平台的集成开发环 ...
- Access自动编号的初始值设置及重置编号 转
方法如下: ALTER TABLE tableName ALTER COLUMN Id COUNTER (100, 5) 其中:tableName为要修改的表名,Id为自动编号列,100为初始值,5为 ...
- dedecms设置文章分页后,标题会带有序号的解决方法
至于删除分页后标题后面的序号,找到include/arc.archives.class.php 打开,找到 if($i>1) $this->Fields['title'] = $this- ...
- nginx 要改进的地方基础
- Python爬虫第一步
这只是记录一下自己学习爬虫的过程,可能少了些章法.我使用过的是Python3.x版本,IDE为Pycharm. 这里贴出代码集合,这一份代码也是以防自己以后忘记了什么,方便查阅. import req ...
- xamarin fivechess
网上的五子棋项目是java开发,先转为xamarin,有需要的请下载. FiveChess.7z
- C++例题1:输出可打印字符
#include<iostream>#include<stdlib.h>#include<cctype>int main(){ int i;char a=0; fo ...