您的位置:首页 > 其它

图片缓存构架

2016-05-08 09:34 309 查看
1、权限

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>


2、视图

1)activity_main.xml

<LinearLayout 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:orientation="vertical"
tools:context=".MainActivity" >

<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/lv"
/>

</LinearLayout>


2)lv_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/iv"
/>

</LinearLayout>


3、MainActivity类

package com.zyh.zyh_imageloader;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.ListView;

public class MainActivity extends Activity {
private ListView lv;
private final String HOST_PATH = "http://192.168.1.100/android/cache_img/thumb/";
private String[] urls = new String[]{
HOST_PATH + "lmm01.jpg",
HOST_PATH + "lmm02.jpg",
HOST_PATH + "lmm03.jpg",
HOST_PATH + "lmm04.jpg",
HOST_PATH + "lmm05.jpg",
HOST_PATH + "lmm06.jpg",
HOST_PATH + "lmm07.jpg",
HOST_PATH + "lmm08.jpg",
HOST_PATH + "lmm09.jpg",
HOST_PATH + "lmm10.jpg",
HOST_PATH + "lmm11.jpg",
HOST_PATH + "lmm12.jpg",
HOST_PATH + "lmm13.jpg",
HOST_PATH + "lmm14.jpg",
HOST_PATH + "lmm15.jpg",
HOST_PATH + "lmm16.jpg",
HOST_PATH + "lmm17.jpg",
HOST_PATH + "lmm18.jpg",
HOST_PATH + "lmm19.jpg",
HOST_PATH + "lmm20.jpg",
HOST_PATH + "lmm21.jpg",
HOST_PATH + "lmm22.jpg",
HOST_PATH + "lmm23.jpg",
HOST_PATH + "lmm24.jpg",
HOST_PATH + "lmm25.jpg",
HOST_PATH + "lmm26.jpg",
HOST_PATH + "lmm27.jpg",
HOST_PATH + "lmm28.jpg",
HOST_PATH + "lmm29.jpg",
HOST_PATH + "lmm30.jpg",
HOST_PATH + "lmm31.jpg",
HOST_PATH + "lmm32.jpg",
HOST_PATH + "lmm33.jpg"
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

lv = (ListView) findViewById(R.id.lv);

lv.setAdapter(new MyAdapter(this,urls));
}

}


4、MyAdapter

package com.zyh.zyh_imageloader;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;

public class MyAdapter extends BaseAdapter {
private Context context;
private LayoutInflater inflater;
private String[] data;
private ImageLoader imageLoader;
public MyAdapter(Context context, String[] data){
this.context = context;
inflater = LayoutInflater.from(this.context);
this.data = data;
imageLoader = ImageLoader.getInstance(context);
}
@Override
public int getCount() {
return data.length;
}

@Override
public Object getItem(int position) {
return data[position];
}

@Override
public long getItemId(int position) {
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if(convertView == null){
holder = new ViewHolder();
convertView = inflater.inflate(R.layout.lv_item, null);
ImageView imageView = (ImageView) convertView.findViewById(R.id.iv);
holder.imageView = imageView;
convertView.setTag(holder);
}else{
holder = (ViewHolder) convertView.getTag();
}
imageLoader.loadImage(data[position], holder.imageView);

return convertView;
}

class ViewHolder{
ImageView imageView;
}

}


5、图片缓存构架类(主要类)

package com.zyh.zyh_imageloader;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.util.LinkedHashMap;
import java.util.concurrent.ConcurrentHashMap;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.AsyncTask;
import android.widget.ImageView;

public class ImageLoader {
private static Context context;
private static final int MAX_CAPACITY = 20;//设置强引用的容量
private DefaultImage defaultImage = new DefaultImage();//默认ImageView的颜色
private static ImageLoader instance = null;

private ImageLoader(){}
//构造函数
private ImageLoader(Context context){
this.context = context;
}

//获取对象
public static ImageLoader getInstance(Context context){
if(instance == null){
instance = new ImageLoader(context);
}
return instance;
}

//一级缓存,强引用
//0.75f是排序因子;true说明是访问排序;false基于插入排序
//LRU最近最少使用算法
private static LinkedHashMap<String, Bitmap> firstCacheMap = new LinkedHashMap<String, Bitmap>(MAX_CAPACITY, 0.75f, true){
//根据返回值,移除map中最老的值
protected boolean removeEldestEntry(java.util.Map.Entry<String,Bitmap> eldest) {
if(this.size() > MAX_CAPACITY){
//加入二级缓存
secondCacheMap.put(eldest.getKey(), new SoftReference<Bitmap>(eldest.getValue()));
//加入本地缓存
diskCache(eldest.getKey(), eldest.getValue());
//移除一级缓存
}
return false;
};
};

//二级缓存,软引用
//线程安全的
private static ConcurrentHashMap<String, SoftReference<Bitmap>> secondCacheMap = new ConcurrentHashMap<String, SoftReference<Bitmap>>();

/**
* @desc 获取图片,如果从缓存中得不到,则从网络中获取
* @param key
* @param imageView
*/
public void loadImage(String key, ImageView imageView){
//从缓存中读取
Bitmap bitmap = getFromCache(key);
if(bitmap != null){
//结束异步任务
//cancelDownload(key, imageView);

imageView.setImageBitmap(bitmap);
}else{
//设置默认图片
imageView.setImageDrawable(defaultImage);

//从网络中读取
AsyncImageLoadTast tast = new AsyncImageLoadTast(imageView);
tast.execute(key);

}

}

/**
* @desc 取消下载
* @param key
* @param imageView
*/
private void cancelDownload(String key, ImageView imageView) {
//可能有多个异步任务在下载同一张图片
AsyncImageLoadTast tast = new AsyncImageLoadTast(imageView);
if(tast != null){
String downloadKey = tast.key;//这个key从何而来
if(downloadKey == null || downloadKey.equals(key)){
tast.cancel(true);
}
}
}
protected static void diskCache(String key, Bitmap value) {
//采用md5方式作为图片名称
String fileName = MD5Utils.decode(key);
String path = context.getCacheDir().getAbsolutePath() + File.separator + fileName;

//jpg
FileOutputStream os = null;
try {
os = new FileOutputStream(path);
value.compress(Bitmap.CompressFormat.JPEG, 100, os);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(os != null){
try {
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

}

class AsyncImageLoadTast extends AsyncTask<String, Void, Bitmap>{
private String key;
private ImageView imageView;

public AsyncImageLoadTast(ImageView imageView) {
super();
this.imageView = imageView;
}

@Override
protected Bitmap doInBackground(String... params) {
key = params[0];
return download(key);
}

@Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
if(isCancelled()){
result = null;
}

if(result != null){
//添加到一级缓存中去
addFirstCache(key, result);
//显示
imageView.setImageBitmap(result);
}
}

}

private Bitmap getFromCache(String key) {
//从一级缓存中获取
synchronized(firstCacheMap){
Bitmap bitmap = firstCacheMap.get(key);
//为了保持最新使用
if(bitmap != null){
firstCacheMap.remove(key);//????不是remove它的key吗?
firstCacheMap.put(key, bitmap);
return bitmap;
}
}

//从二级缓存中获取
SoftReference<Bitmap> soft_bitmap = secondCacheMap.get(key);
if(soft_bitmap != null){
Bitmap bitmap = soft_bitmap.get();
if(bitmap != null){
//firstCacheMap.put(key, bitmap);
addFirstCache(key, bitmap);
return bitmap;
}
}else{
secondCacheMap.remove(key);
}

//从本地获取
Bitmap local_bitmap = getFromLocal(key);
if(local_bitmap != null){
//firstCacheMap.put(key, local_bitmap);
addFirstCache(key, local_bitmap);
return local_bitmap;
}
return null;
}

private Bitmap getFromLocal(String key) {
String fileName = MD5Utils.decode(key);
if(fileName == null){
return null;
}

String path = context.getCacheDir().getAbsolutePath() + File.separator + fileName;

FileInputStream is = null;
try {
is = new FileInputStream(path);
return BitmapFactory.decodeStream(is);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
if(is != null){
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}

public void addFirstCache(String key, Bitmap bitmap) {
if(bitmap != null){
synchronized(firstCacheMap){
firstCacheMap.put(key, bitmap);
}
}
}

public Bitmap download(String key) {
InputStream is = null;
try {
is = HttpUtils.download(key);
return BitmapFactory.decodeStream(is);
} catch (Exception e) {
e.printStackTrace();
}finally{
if(is != null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}

class DefaultImage extends ColorDrawable{
public DefaultImage(){
super(Color.BLUE);
}
}
}


6、辅助类

package com.zyh.zyh_imageloader;

import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class HttpUtils {
public static InputStream download(String key) throws Exception{
HttpURLConnection conn = (HttpURLConnection) new URL(key).openConnection();
return conn.getInputStream();
}
}


package com.zyh.zyh_imageloader;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class MD5Utils {
public static String decode(String info){
try
{
MessageDigest md5 = MessageDigest.getInstance("MD5");
md5.update(info.getBytes("UTF-8"));
byte[] encryption = md5.digest();

StringBuffer strBuf = new StringBuffer();
for (int i = 0; i < encryption.length; i++)
{
if (Integer.toHexString(0xff & encryption[i]).length() == 1)
{
strBuf.append("0").append(Integer.toHexString(0xff & encryption[i]));
}
else
{
strBuf.append(Integer.toHexString(0xff & encryption[i]));
}
}

return strBuf.toString();
}
catch (NoSuchAlgorithmException e)
{
return "";
}
catch (UnsupportedEncodingException e)
{
return "";
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: