Android LruCache DiskCache的总结

来源:互联网 发布:mac的hosts文件在哪 编辑:程序博客网 时间:2024/06/05 00:10




public class PhotoWallAdapter extends ArrayAdapter<String> {/** * 记录所有正在下载或等待下载的任务。 */private Set<BitmapWorkerTask> taskCollection;/** * 图片缓存技术的核心类,用于缓存所有下载好的图片,在程序内存达到设定值时会将最少最近使用的图片移除掉。 */private LruCache<String, Bitmap> mMemoryCache;/** * 图片硬盘缓存核心类。 */private DiskLruCache mDiskLruCache;/** * GridView的实例 */private GridView mPhotoWall;/** * 记录每个子项的高度。 */private int mItemHeight = 0;public PhotoWallAdapter(Context context, int textViewResourceId, String[] objects,GridView photoWall) {super(context, textViewResourceId, objects);mPhotoWall = photoWall;taskCollection = new HashSet<BitmapWorkerTask>();// 获取应用程序最大可用内存int maxMemory = (int) Runtime.getRuntime().maxMemory();int cacheSize = maxMemory / 8;// 设置图片缓存大小为程序最大可用内存的1/8mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {@Overrideprotected int sizeOf(String key, Bitmap bitmap) {return bitmap.getByteCount();}};try {// 获取图片缓存路径File cacheDir = getDiskCacheDir(context, "thumb");if (!cacheDir.exists()) {cacheDir.mkdirs();}// 创建DiskLruCache实例,初始化缓存数据mDiskLruCache = DiskLruCache.open(cacheDir, getAppVersion(context), 1, 10 * 1024 * 1024);} catch (IOException e) {e.printStackTrace();}}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {final String url = getItem(position);View view;if (convertView == null) {view = LayoutInflater.from(getContext()).inflate(R.layout.photo_layout, null);} else {view = convertView;}final ImageView imageView = (ImageView) view.findViewById(R.id.photo);if (imageView.getLayoutParams().height != mItemHeight) {imageView.getLayoutParams().height = mItemHeight;}// 给ImageView设置一个Tag,保证异步加载图片时不会乱序imageView.setTag(url);imageView.setImageResource(R.drawable.empty_photo);loadBitmaps(imageView, url);return view;}/** * 将一张图片存储到LruCache中。 *  * @param key *            LruCache的键,这里传入图片的URL地址。 * @param bitmap *            LruCache的键,这里传入从网络上下载的Bitmap对象。 */public void addBitmapToMemoryCache(String key, Bitmap bitmap) {if (getBitmapFromMemoryCache(key) == null) {mMemoryCache.put(key, bitmap);}}/** * 从LruCache中获取一张图片,如果不存在就返回null。 *  * @param key *            LruCache的键,这里传入图片的URL地址。 * @return 对应传入键的Bitmap对象,或者null。 */public Bitmap getBitmapFromMemoryCache(String key) {return mMemoryCache.get(key);}/** * 加载Bitmap对象。此方法会在LruCache中检查所有屏幕中可见的ImageView的Bitmap对象, * 如果发现任何一个ImageView的Bitmap对象不在缓存中,就会开启异步线程去下载图片。 */public void loadBitmaps(ImageView imageView, String imageUrl) {try {Bitmap bitmap = getBitmapFromMemoryCache(imageUrl);if (bitmap == null) {BitmapWorkerTask task = new BitmapWorkerTask();taskCollection.add(task);task.execute(imageUrl);} else {if (imageView != null && bitmap != null) {imageView.setImageBitmap(bitmap);}}} catch (Exception e) {e.printStackTrace();}}/** * 取消所有正在下载或等待下载的任务。 */public void cancelAllTasks() {if (taskCollection != null) {for (BitmapWorkerTask task : taskCollection) {task.cancel(false);}}}/** * 根据传入的uniqueName获取硬盘缓存的路径地址。 */public File getDiskCacheDir(Context context, String uniqueName) {String cachePath;if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())|| !Environment.isExternalStorageRemovable()) {cachePath = context.getExternalCacheDir().getPath();} else {cachePath = context.getCacheDir().getPath();}return new File(cachePath + File.separator + uniqueName);}/** * 获取当前应用程序的版本号。 */public int getAppVersion(Context context) {try {PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(),0);return info.versionCode;} catch (NameNotFoundException e) {e.printStackTrace();}return 1;}/** * 设置item子项的高度。 */public void setItemHeight(int height) {if (height == mItemHeight) {return;}mItemHeight = height;notifyDataSetChanged();}/** * 使用MD5算法对传入的key进行加密并返回。 */public String hashKeyForDisk(String key) {String cacheKey;try {final MessageDigest mDigest = MessageDigest.getInstance("MD5");mDigest.update(key.getBytes());cacheKey = bytesToHexString(mDigest.digest());} catch (NoSuchAlgorithmException e) {cacheKey = String.valueOf(key.hashCode());}return cacheKey;}/** * 将缓存记录同步到journal文件中。 */public void fluchCache() {if (mDiskLruCache != null) {try {mDiskLruCache.flush();} catch (IOException e) {e.printStackTrace();}}}private String bytesToHexString(byte[] bytes) {StringBuilder sb = new StringBuilder();for (int i = 0; i < bytes.length; i++) {String hex = Integer.toHexString(0xFF & bytes[i]);if (hex.length() == 1) {sb.append('0');}sb.append(hex);}return sb.toString();}/** * 异步下载图片的任务。 *  * @author guolin */class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {/** * 图片的URL地址 */private String imageUrl;@Overrideprotected Bitmap doInBackground(String... params) {imageUrl = params[0];FileDescriptor fileDescriptor = null;FileInputStream fileInputStream = null;Snapshot snapShot = null;try {// 生成图片URL对应的keyfinal String key = hashKeyForDisk(imageUrl);// 查找key对应的缓存snapShot = mDiskLruCache.get(key);if (snapShot == null) {// 如果没有找到对应的缓存,则准备从网络上请求数据,并写入缓存DiskLruCache.Editor editor = mDiskLruCache.edit(key);if (editor != null) {OutputStream outputStream = editor.newOutputStream(0);if (downloadUrlToStream(imageUrl, outputStream)) {editor.commit();} else {editor.abort();}}// 缓存被写入后,再次查找key对应的缓存snapShot = mDiskLruCache.get(key);}if (snapShot != null) {fileInputStream = (FileInputStream) snapShot.getInputStream(0);fileDescriptor = fileInputStream.getFD();}// 将缓存数据解析成Bitmap对象Bitmap bitmap = null;if (fileDescriptor != null) {bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);}if (bitmap != null) {// 将Bitmap对象添加到内存缓存当中addBitmapToMemoryCache(params[0], bitmap);}return bitmap;} catch (IOException e) {e.printStackTrace();} finally {if (fileDescriptor == null && fileInputStream != null) {try {fileInputStream.close();} catch (IOException e) {}}}return null;}@Overrideprotected void onPostExecute(Bitmap bitmap) {super.onPostExecute(bitmap);// 根据Tag找到相应的ImageView控件,将下载好的图片显示出来。ImageView imageView = (ImageView) mPhotoWall.findViewWithTag(imageUrl);if (imageView != null && bitmap != null) {imageView.setImageBitmap(bitmap);}taskCollection.remove(this);}/** * 建立HTTP请求,并获取Bitmap对象。 *  * @param imageUrl *            图片的URL地址 * @return 解析后的Bitmap对象 */private boolean downloadUrlToStream(String urlString, OutputStream outputStream) {HttpURLConnection urlConnection = null;BufferedOutputStream out = null;BufferedInputStream in = null;try {final URL url = new URL(urlString);urlConnection = (HttpURLConnection) url.openConnection();in = new BufferedInputStream(urlConnection.getInputStream(), 8 * 1024);out = new BufferedOutputStream(outputStream, 8 * 1024);int b;while ((b = in.read()) != -1) {out.write(b);}return true;} catch (final IOException e) {e.printStackTrace();} finally {if (urlConnection != null) {urlConnection.disconnect();}try {if (out != null) {out.close();}if (in != null) {in.close();}} catch (final IOException e) {e.printStackTrace();}}return false;}}}


0 0