码迷,mamicode.com
首页 > 其他好文 > 详细

图片缓存构架

时间:2016-05-08 10:22:52      阅读:232      评论:0      收藏:0      [点我收藏+]

标签:

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

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical"
 6     tools:context=".MainActivity" >
 7 
 8     <ListView
 9         android:layout_width="wrap_content"
10         android:layout_height="wrap_content"
11         android:id="@+id/lv"
12         />
13 
14 </LinearLayout>

2)lv_item.xml

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical" >
 6     <ImageView 
 7         android:layout_width="wrap_content"
 8         android:layout_height="wrap_content"
 9         android:id="@+id/iv"
10         />
11 
12 </LinearLayout>

3、MainActivity类

 1 package com.zyh.zyh_imageloader;
 2 
 3 import android.os.Bundle;
 4 import android.app.Activity;
 5 import android.view.Menu;
 6 import android.widget.ListView;
 7 
 8 public class MainActivity extends Activity {
 9     private ListView lv;
10     private final String HOST_PATH = "http://192.168.1.100/android/cache_img/thumb/";
11     private String[] urls = new String[]{
12             HOST_PATH + "lmm01.jpg",
13             HOST_PATH + "lmm02.jpg",
14             HOST_PATH + "lmm03.jpg",
15             HOST_PATH + "lmm04.jpg",
16             HOST_PATH + "lmm05.jpg",
17             HOST_PATH + "lmm06.jpg",
18             HOST_PATH + "lmm07.jpg",
19             HOST_PATH + "lmm08.jpg",
20             HOST_PATH + "lmm09.jpg",
21             HOST_PATH + "lmm10.jpg",
22             HOST_PATH + "lmm11.jpg",
23             HOST_PATH + "lmm12.jpg",
24             HOST_PATH + "lmm13.jpg",
25             HOST_PATH + "lmm14.jpg",
26             HOST_PATH + "lmm15.jpg",
27             HOST_PATH + "lmm16.jpg",
28             HOST_PATH + "lmm17.jpg",
29             HOST_PATH + "lmm18.jpg",
30             HOST_PATH + "lmm19.jpg",
31             HOST_PATH + "lmm20.jpg",
32             HOST_PATH + "lmm21.jpg",
33             HOST_PATH + "lmm22.jpg",
34             HOST_PATH + "lmm23.jpg",
35             HOST_PATH + "lmm24.jpg",
36             HOST_PATH + "lmm25.jpg",
37             HOST_PATH + "lmm26.jpg",
38             HOST_PATH + "lmm27.jpg",
39             HOST_PATH + "lmm28.jpg",
40             HOST_PATH + "lmm29.jpg",
41             HOST_PATH + "lmm30.jpg",
42             HOST_PATH + "lmm31.jpg",
43             HOST_PATH + "lmm32.jpg",
44             HOST_PATH + "lmm33.jpg"
45     };
46     @Override
47     protected void onCreate(Bundle savedInstanceState) {
48         super.onCreate(savedInstanceState);
49         setContentView(R.layout.activity_main);
50         
51         lv = (ListView) findViewById(R.id.lv);
52         
53         lv.setAdapter(new MyAdapter(this,urls));
54     }
55 
56 }

4、MyAdapter

 1 package com.zyh.zyh_imageloader;
 2 
 3 import android.content.Context;
 4 import android.view.LayoutInflater;
 5 import android.view.View;
 6 import android.view.ViewGroup;
 7 import android.widget.BaseAdapter;
 8 import android.widget.ImageView;
 9 
10 public class MyAdapter extends BaseAdapter {
11     private Context context;
12     private LayoutInflater inflater;
13     private String[] data;
14     private ImageLoader imageLoader;
15     public MyAdapter(Context context, String[] data){
16         this.context = context;
17         inflater = LayoutInflater.from(this.context);
18         this.data = data;
19         imageLoader = ImageLoader.getInstance(context);
20     }
21     @Override
22     public int getCount() {
23         return data.length;
24     }
25 
26     @Override
27     public Object getItem(int position) {
28         return data[position];
29     }
30 
31     @Override
32     public long getItemId(int position) {
33         return position;
34     }
35 
36     @Override
37     public View getView(int position, View convertView, ViewGroup parent) {
38         ViewHolder holder = null;
39         if(convertView == null){
40             holder = new ViewHolder();
41             convertView = inflater.inflate(R.layout.lv_item, null);
42             ImageView imageView = (ImageView) convertView.findViewById(R.id.iv);
43             holder.imageView = imageView;
44             convertView.setTag(holder);
45         }else{
46             holder = (ViewHolder) convertView.getTag();
47         }
48         imageLoader.loadImage(data[position], holder.imageView);
49         
50         return convertView;
51     }
52     
53     class ViewHolder{
54         ImageView imageView;
55     }
56 
57 }

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

  1 package com.zyh.zyh_imageloader;
  2 
  3 import java.io.File;
  4 import java.io.FileInputStream;
  5 import java.io.FileNotFoundException;
  6 import java.io.FileOutputStream;
  7 import java.io.IOException;
  8 import java.io.InputStream;
  9 import java.lang.ref.SoftReference;
 10 import java.util.LinkedHashMap;
 11 import java.util.concurrent.ConcurrentHashMap;
 12 
 13 import android.content.Context;
 14 import android.graphics.Bitmap;
 15 import android.graphics.BitmapFactory;
 16 import android.graphics.Color;
 17 import android.graphics.drawable.ColorDrawable;
 18 import android.os.AsyncTask;
 19 import android.widget.ImageView;
 20 
 21 public class ImageLoader {
 22     private static Context context;
 23     private static final int MAX_CAPACITY = 20;//设置强引用的容量
 24     private DefaultImage defaultImage = new DefaultImage();//默认ImageView的颜色
 25     private static ImageLoader instance = null;
 26     
 27     private ImageLoader(){}
 28     //构造函数
 29     private ImageLoader(Context context){
 30         this.context = context;
 31     }
 32     
 33     //获取对象
 34     public static ImageLoader getInstance(Context context){
 35         if(instance == null){
 36             instance = new ImageLoader(context);
 37         }
 38         return instance;
 39     }
 40     
 41     //一级缓存,强引用
 42     //0.75f是排序因子;true说明是访问排序;false基于插入排序
 43     //LRU最近最少使用算法
 44     private static LinkedHashMap<String, Bitmap> firstCacheMap = new LinkedHashMap<String, Bitmap>(MAX_CAPACITY, 0.75f, true){
 45         //根据返回值,移除map中最老的值
 46         protected boolean removeEldestEntry(java.util.Map.Entry<String,Bitmap> eldest) {
 47             if(this.size() > MAX_CAPACITY){
 48                 //加入二级缓存
 49                 secondCacheMap.put(eldest.getKey(), new SoftReference<Bitmap>(eldest.getValue()));
 50                 //加入本地缓存
 51                 diskCache(eldest.getKey(), eldest.getValue());
 52                 //移除一级缓存
 53             }
 54             return false;
 55         };
 56     };
 57     
 58     //二级缓存,软引用
 59     //线程安全的
 60     private static ConcurrentHashMap<String, SoftReference<Bitmap>> secondCacheMap = new ConcurrentHashMap<String, SoftReference<Bitmap>>();
 61 
 62     /**
 63      * @desc 获取图片,如果从缓存中得不到,则从网络中获取
 64      * @param key
 65      * @param imageView
 66      */
 67     public void loadImage(String key, ImageView imageView){
 68         //从缓存中读取
 69         Bitmap bitmap = getFromCache(key);
 70         if(bitmap != null){
 71             //结束异步任务
 72             //cancelDownload(key, imageView);
 73             
 74             imageView.setImageBitmap(bitmap);
 75         }else{
 76             //设置默认图片
 77             imageView.setImageDrawable(defaultImage);
 78             
 79             //从网络中读取
 80             AsyncImageLoadTast tast = new AsyncImageLoadTast(imageView);
 81             tast.execute(key);
 82             
 83         }
 84         
 85     }
 86     
 87     /**
 88      * @desc 取消下载
 89      * @param key
 90      * @param imageView
 91      */
 92     private void cancelDownload(String key, ImageView imageView) {
 93         //可能有多个异步任务在下载同一张图片
 94         AsyncImageLoadTast tast = new AsyncImageLoadTast(imageView);
 95         if(tast != null){
 96             String downloadKey = tast.key;//这个key从何而来
 97             if(downloadKey == null || downloadKey.equals(key)){
 98                 tast.cancel(true);
 99             }
100         }
101     }
102     protected static void diskCache(String key, Bitmap value) {
103         //采用md5方式作为图片名称
104         String fileName = MD5Utils.decode(key);
105         String path = context.getCacheDir().getAbsolutePath() + File.separator + fileName;
106         
107         //jpg
108         FileOutputStream os = null;
109         try {
110             os = new FileOutputStream(path);
111             value.compress(Bitmap.CompressFormat.JPEG, 100, os);
112         } catch (FileNotFoundException e) {
113             // TODO Auto-generated catch block
114             e.printStackTrace();
115         }finally{
116             if(os != null){
117                 try {
118                     os.close();
119                 } catch (IOException e) {
120                     // TODO Auto-generated catch block
121                     e.printStackTrace();
122                 }
123             }
124         }
125         
126     }
127 
128     class AsyncImageLoadTast extends AsyncTask<String, Void, Bitmap>{
129         private String key;
130         private ImageView imageView;
131         
132         public AsyncImageLoadTast(ImageView imageView) {
133             super();
134             this.imageView = imageView;
135         }
136 
137         @Override
138         protected Bitmap doInBackground(String... params) {
139             key = params[0];
140             return download(key);
141         }
142 
143         @Override
144         protected void onPostExecute(Bitmap result) {
145             super.onPostExecute(result);
146             if(isCancelled()){
147                 result = null;
148             }
149             
150             if(result != null){
151                 //添加到一级缓存中去
152                 addFirstCache(key, result);
153                 //显示
154                 imageView.setImageBitmap(result);
155             }
156         }
157         
158         
159         
160     }
161 
162 
163     private Bitmap getFromCache(String key) {
164         //从一级缓存中获取
165         synchronized(firstCacheMap){
166             Bitmap bitmap = firstCacheMap.get(key);
167             //为了保持最新使用
168             if(bitmap != null){
169                 firstCacheMap.remove(key);//????不是remove它的key吗?
170                 firstCacheMap.put(key, bitmap);
171                 return bitmap;
172             }
173         }
174         
175         //从二级缓存中获取
176         SoftReference<Bitmap> soft_bitmap = secondCacheMap.get(key);
177         if(soft_bitmap != null){
178             Bitmap bitmap = soft_bitmap.get();
179             if(bitmap != null){
180                 //firstCacheMap.put(key, bitmap);
181                 addFirstCache(key, bitmap);
182                 return bitmap;
183             }
184         }else{
185             secondCacheMap.remove(key);
186         }
187         
188         //从本地获取
189         Bitmap local_bitmap = getFromLocal(key);
190         if(local_bitmap != null){
191             //firstCacheMap.put(key, local_bitmap);
192             addFirstCache(key, local_bitmap);
193             return local_bitmap;
194         }
195         return null;
196     }
197 
198 
199     
200 
201 
202     private Bitmap getFromLocal(String key) {
203         String fileName = MD5Utils.decode(key);
204         if(fileName == null){
205             return null;
206         }
207         
208         String path = context.getCacheDir().getAbsolutePath() + File.separator + fileName;
209         
210         FileInputStream is = null;
211         try {
212             is = new FileInputStream(path);
213             return BitmapFactory.decodeStream(is);
214         } catch (FileNotFoundException e) {
215             // TODO Auto-generated catch block
216             e.printStackTrace();
217         }finally{
218             if(is != null){
219                 try {
220                     is.close();
221                 } catch (IOException e) {
222                     // TODO Auto-generated catch block
223                     e.printStackTrace();
224                 }
225             }
226         }
227         return null;
228     }
229 
230     public void addFirstCache(String key, Bitmap bitmap) {
231         if(bitmap != null){
232             synchronized(firstCacheMap){
233                 firstCacheMap.put(key, bitmap);
234             }
235         }
236     }
237 
238 
239 
240 
241 
242     public Bitmap download(String key) {
243         InputStream is = null;
244         try {
245             is = HttpUtils.download(key);
246             return BitmapFactory.decodeStream(is);
247         } catch (Exception e) {
248             e.printStackTrace();
249         }finally{
250             if(is != null){
251                 try {
252                     is.close();
253                 } catch (IOException e) {
254                     e.printStackTrace();
255                 }
256             }
257         }
258         return null;
259     }
260     
261     class DefaultImage extends ColorDrawable{
262         public DefaultImage(){
263             super(Color.BLUE);
264         }
265     }
266 }

6、辅助类

 1 package com.zyh.zyh_imageloader;
 2 
 3 import java.io.InputStream;
 4 import java.net.HttpURLConnection;
 5 import java.net.URL;
 6 
 7 public class HttpUtils {
 8     public static InputStream download(String key) throws Exception{
 9         HttpURLConnection conn = (HttpURLConnection) new URL(key).openConnection();
10         return conn.getInputStream();
11     }
12 }
 1 package com.zyh.zyh_imageloader;
 2 
 3 import java.io.UnsupportedEncodingException;
 4 import java.security.MessageDigest;
 5 import java.security.NoSuchAlgorithmException;
 6 
 7 public class MD5Utils {
 8     public static String decode(String info){
 9         try
10           {
11             MessageDigest md5 = MessageDigest.getInstance("MD5");
12             md5.update(info.getBytes("UTF-8"));
13             byte[] encryption = md5.digest();
14               
15             StringBuffer strBuf = new StringBuffer();
16             for (int i = 0; i < encryption.length; i++)
17             {
18               if (Integer.toHexString(0xff & encryption[i]).length() == 1)
19               {
20                 strBuf.append("0").append(Integer.toHexString(0xff & encryption[i]));
21               }
22               else
23               {
24                 strBuf.append(Integer.toHexString(0xff & encryption[i]));
25               }
26             }
27               
28             return strBuf.toString();
29           }
30           catch (NoSuchAlgorithmException e)
31           {
32             return "";
33           }
34           catch (UnsupportedEncodingException e)
35           {
36             return "";
37           }
38     }
39 }

 

图片缓存构架

标签:

原文地址:http://www.cnblogs.com/zhongyinghe/p/5469809.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!