图片缓存构架
2016-05-08 09:34
309 查看
1、权限
2、视图
1)activity_main.xml
2)lv_item.xml
3、MainActivity类
4、MyAdapter
5、图片缓存构架类(主要类)
6、辅助类
<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 ""; } } }
相关文章推荐
- [转]深入理解Java的接口和抽象类
- bzoj 4010: [HNOI2015]菜肴制作(优先队列+拓扑排序)
- 使用android studio的配置及注意事项
- Linux设备驱动(1)模块的相关概念
- Python数据类型详解(二)列表
- 继承和组合、多态性和虚函数
- iOS-HTTP浅析
- 设置每CPU环境
- 各种信息图应用说明
- IntelliJ IDEA —— SVN
- Hybrid APP 架构设计思路
- 第九章:逻辑卷LVM
- 排序算法(综述)
- java课程总结
- *Divide Two Integers
- slab----1
- 第八章:软件包的安装与管理
- Codeforces Round #351 Div2 C 简单枚举
- 神奇的系统请求键SysRq
- 客户端携带版本号码去访问服务端