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 ...
随机推荐
- jQuery-弹窗登录
在jQuery中实现弹窗常要用到的方法有: width() :元素的宽度 outerWidth() 元素的宽度 盒子的padding+border 总的宽度 scrollTop() 鼠标滚轮自上 ...
- CSS lib
Yahoo的轻型CSS框架Pure来加速web开发 http://purecss.io/buttons/#
- Flask-SQLALchemy查询
from: http://blog.sina.com.cn/s/blog_633277f90100kpvm.html 似乎ORM最难设计的部分是查询.特别是面向对象的查询,今天学习SQLAlchemy ...
- Centos yum install
http://wiki.centos.org/TipsAndTricks/BrokenVserver centos mirror: http://mirror.centos.org/centos/6 ...
- gridview checkbox从服务器端和客户端两个方面实现全选和反选
GridView中的checkbox的全选和反选在很多的地方都是要求实现的,所以下面就从服务器端和客户端两个方面实现了checkbox的选择,感兴趣的朋友可以了解下,希望本文对你有所帮助 GridVi ...
- BZOJ 1263 整数划分
Description 从文件中读入一个正整数\(n\).要求将\(n\)写成若干个正整数之和,并且使这些正整数的乘积最大. 例如,\(n=13\),则当\(n\)表示为\(4+3+3+3\)(或\( ...
- BZOJ 1067 降雨量
Description 我们常常会说这样的话:"\(X\)年是自\(Y\)年以来降雨量最多的".它的含义是\(X\)年的降雨量不超过\(Y\)年,且对于任意\(Y<Z< ...
- Pots
poj3414:http://poj.org/problem?id=3414 题意:给你两个罐子的体积,然后让你只用这两个罐子量出给定k体积的水.题解:这里可以把两个罐子看成是一个二维的图,然后体积的 ...
- Android Wear开发 - 数据通讯 - 第四节 : 数据封装(解决不能序列化问题)
一. 前言 背景 一开始笔者在研究数据发送与接收的时候,看到Wear数据类DataMap除了可以put基本类型外,还有个fromBundle方法来构建一个DataMap对象.所以一口气的将原本功能上的 ...
- zabbix 四张大表分区
trends_uint.ibd history history_unit trends CREATE TABLE `trends` ( `itemid` bigint(20) unsigned NOT ...