您的位置:首页 > 理论基础 > 计算机网络

Android (LruCache+外部存储缓存)实现网络下载图片并缓存

2016-09-24 23:57 537 查看
目录:
1.缓存概述
2.外部缓存与内存缓存(LruCache)的区别
3.内存缓存(LruCache)+外部缓存实现网络下载图片并缓存

1.概述:
学一个知识点之前首先需要明白为什么他会出现,他的作用是啥,满足了啥需求?后面再学习它的使用也不迟。今天我们要学习

的就是android的缓存技术中的LruCache(内存缓存)和外部缓存,首先我们来看看缓存技术的出现解决了啥问题呢?我相信朋友们在使用手机的过程中

都会有浏览大量网络图片的需求,如果开发不加入缓存技术的话,你每次进入页面时它都会重新去网络加载上次加载过的内容导致重复

加载非常耗流量,同时加载的速度受网络状况的影响,如果网不好加载会很慢,也影响用户体验,所以缓存技术的应用是非常有必要的。

明白了缓存的作用,我接下来看看缓存中LruCache和本地缓存的区别。

2.外部缓存与内存缓存(LruCache)的区别
内存缓存(LruCache):
概述:外部缓存也就是磁盘缓存或者外部存储卡缓存
优点:加载快
缺点:占用内存,应用重启消失
外部缓存:
优点:可以长期保存,查看
缺点:相比内存缓存加载慢

3.内存缓存(LruCache)+外部缓存实现网络下载图片并缓存
1.概述:下面的示例实现了从网络下载图片缓存到内存和外部存储,在点击请求中采用了3种加载模式,如果LruCache中已经有了,则直接从

LruCache中加载,如果没有,则看看外部是否缓存,如果仍然没有则通过网络下载。

2.先上截图





3.主布局文件activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.lrucache.MainActivity">
<ImageView
android:id="@+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<Button
android:layout_marginTop="10dp"
android:id="@+id/show_bnt"
android:layout_below="@+id/image"
android:text="show"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>

4.主布局类MainActivity.java
package com.example.lrucache;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private ImageView imageView;
private Button button;
private String imageUrl="http://img.pconline.com.cn/images/upload/upc/tx/wallpaper/1606/28/c0/23485424_1467120124322_200x300.jpg";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//绑定控件
imageView = (ImageView) findViewById(R.id.image);
button = (Button) findViewById(R.id.show_bnt);
//设置监听
button.setOnClickListener(this);
}
/*
* 设置按钮监听,点击执行从缓存加载图片或从网络下载图片进行显示
* */
@Override
public void onClick(View v) {
AsyncLoadImageTask asyncTask = new AsyncLoadImageTask(imageView);
asyncTask.execute(imageUrl);
}
}

5.异步线程类AsyncLoadImageTask.java
package com.example.lrucache;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Environment;
import android.util.Log;
import android.widget.ImageView;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

/**
* Created by elimy on 2016-09-24.
*/
public class AsyncLoadImageTask extends AsyncTask<String, Void, Bitmap> {
ImageView imageView = null;
Bitmap bitmap;
ImageCacheManager imageCacheManager = ImageCacheManager.getInstance();

/*
* 无参构造方法
* */
public AsyncLoadImageTask() {
}

/*
* 带参构造方法实现传递参数的效果
* */
public AsyncLoadImageTask(ImageView imageView) {
this.imageView = imageView;
}

/*
* 执行后台操作,获取图片bitmap
* */
@Override
protected Bitmap doInBackground(String... params) {
String urlSpec = params[0];
//如果缓存没有则去本地文件缓存文件夹获取,如果还没有则去网络加载
bitmap = imageCacheManager.getBitmapFromCache(urlSpec);
if (bitmap == null) {
File imageFile = new File(getImagePath(urlSpec));
if (imageFile.exists()) {
bitmap = BitmapFactory.decodeFile(imageFile.getPath());
Log.d("Tag","从本地文件缓存中加载...");
} else {
//网络获取图片
bitmap = downloadImage(urlSpec);
Log.d("Tag","从网络中下载...");
}
}else {
Log.d("Tag","从LruCache中加载...");
}
return bitmap;
}

/*
* 后台线程执行操作后返回图片bitmap,该方法执行更新UI的操作
* */
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
imageView.setImageBitmap(bitmap);
}

/*
* 从网络下载图片并缓存
* */
private Bitmap downloadImage(String urlSpec) {
URL url = null;
HttpURLConnection urlConn = null;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
File imageFile = null;
FileOutputStream fos = null;
try {
url = new URL(urlSpec);
urlConn = (HttpURLConnection) url.openConnection();
urlConn.setRequestMethod("GET");
urlConn.setDoInput(true);
urlConn.setConnectTimeout(5000);
urlConn.setReadTimeout(5000);
if (urlConn.getResponseCode() ==HttpURLConnection.HTTP_OK){
bis = new BufferedInputStream(urlConn.getInputStream());
imageFile = new File(getImagePath(urlSpec));
fos = new FileOutputStream(imageFile);
bos = new BufferedOutputStream(fos);
int len = 0;
byte[] b =new byte[1024];
while ((len =bis.read(b))!=-1){
bos.write(b,0,len);
bos.flush();
}
}else {
Log.d("getResponseCode","下载失败!");
}

} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if (bis != null) {
bis.close();
}
if (bos != null) {
bos.close();
}
if (fos != null) {
fos.close();
}
if (urlConn != null) {
urlConn.disconnect();
}
} catch (IOException e) {
e.printStackTrace();
}
}
if (imageFile!=null){
Bitmap bitmap = BitmapFactory.decodeFile(getImagePath(urlSpec));
if (bitmap != null){
imageCacheManager.addBitmapToCache(urlSpec,bitmap);
return  bitmap;
}
}
return null;
}
/*
* 该方法用来获取缓存图片的全地址也就是绝对地址+文件名
*
* */
private String getImagePath(String urlSpec) {
//截取urlSpec最后一个“/”后面的字符串作为文件名
String imageName = urlSpec.substring(urlSpec.lastIndexOf("/") + 1);
//定义图片缓存本地路径
String imageDir = Environment.getExternalStorageDirectory() + "/LruCache/";
File file = new File(imageDir);
if (!file.exists()) {
file.mkdirs();
Log.d("file", "file make success");
}
String path = imageDir + imageName;
Log.d("path", path);
return path;
}
}

6.LruCache缓存管理类ImageCacheManager.java
package com.example.lrucache;

import android.graphics.Bitmap;
import android.util.LruCache;

/**
* Created by elimy on 2016-09-24.
*/
public class ImageCacheManager {
//设置缓存大小为最大缓存的1/8
private static final int mCacheSize = (int) (Runtime.getRuntime().maxMemory()/8);
//定义缓存核心类
static LruCache<String,Bitmap> mImageCache;
//定义类本身实例
private static ImageCacheManager imageCacheManager;

private ImageCacheManager(){
mImageCache = new LruCache<String,Bitmap>(mCacheSize){
/*
*返回图片的占用控件,每次添加图片时会被调用
* */
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
};
}
/*
* 单例模式实现初始化ImageCacheManager类,好处是在整个操作过程中保持
* 仅有一个实例,以此来节约系统资源
* */
public static ImageCacheManager getInstance(){
if (imageCacheManager == null){
imageCacheManager = new ImageCacheManager();
}
return imageCacheManager;
}
/*
* 从缓存中获取bitmap
* */
public Bitmap getBitmapFromCache(String urlSpec){
return mImageCache.get(urlSpec);
}
/*
* 缓存图片
* */
public void addBitmapToCache(String url,Bitmap bitmap){
if (mImageCache.get(url)==null){
mImageCache.put(url,bitmap);
}
}
}

7.需要声明的权限
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

推荐文章:http://www.codeceo.com/article/android-memory-cache.html
http://www.voidcn.com/blog/Greathfs/article/p-6179189.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息