偶遇DiskLruCache(缓存策略解析)

根据郭神的博客写了个小demo,详细的方法都卸载注释里了,先上效果图:



技术分享


布局代码:

<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="com.example.disklrucache.MainActivity" >

    <ScrollView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/showSize"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="25sp" />

            <Button
                android:id="@+id/read"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="缓存图片" />

            <Button
                android:id="@+id/remove"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="移除缓存图片" />
            
            <Button
                android:id="@+id/delete"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="删除全部缓存(包括日志文件)"/>

            <Button
                android:id="@+id/show"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="显示图片" />

            <ImageView
                android:id="@+id/img"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
        </LinearLayout>
    </ScrollView>

</LinearLayout>



主Activity代码

package com.example.disklrucache;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import libcore.io.DiskLruCache;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {

	String imageUrl = "http://img.my.csdn.net/uploads/201309/01/1378037235_7476.jpg";  
	private DiskLruCache lruCache = null ;
	private TextView showSize ;    //缓存区的大小
	private ImageView img ;
	private Button read,show ;  //读取,与现实在屏幕上
	private Button remove ;   //移除缓存文件但是保留操作日志
	private Button delete ;     //删除缓存
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE) ;
		setContentView(R.layout.activity_main);
		this.read = (Button)findViewById(R.id.read) ;
		this.remove = (Button)findViewById(R.id.remove) ;
		this.show = (Button)findViewById(R.id.show) ;
		this.delete = (Button)findViewById(R.id.delete) ;
		this.showSize = (TextView) findViewById(R.id.showSize) ;
		img = (ImageView) findViewById(R.id.img) ;
		File file = getDiskCacheDir(MainActivity.this, "bitmap") ;
		if(!file.exists()) {
			file.mkdirs() ;
		}
		try {
			lruCache = DiskLruCache.open(file, getAppVersion(MainActivity.this), 1, 10*1024*1024) ;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		this.show.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				getCacheBitmap();
				showSize.setText("当前缓存尺寸:"+lruCache.size());

			}
		});
		this.read.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				new Thread(new Runnable() {

					@Override
					public void run() {
						// TODO Auto-generated method stub
						String key = hashKeyForDisk(imageUrl) ;     //生成key
						DiskLruCache.Editor editor;
						try {
							editor = lruCache.edit(key);
							if(editor != null) {
								OutputStream out = editor.newOutputStream(0) ;
								if(downUrlToStream(imageUrl, out)) {
									editor.commit();
								} else {
									editor.abort();
								}
							}
						} catch (IOException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}  //将key传入editor
					}
				}).start();

			}
		});

		this.remove.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				try {  
					String key = hashKeyForDisk(imageUrl);    
					lruCache.remove(key);  
				} catch (IOException e) {  
					e.printStackTrace();  
				}  
			}
		});

		this.delete.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				try {
					lruCache.delete();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		});

		//getCacheBitmap();     //读取下载的图片
	}


	/*
	 * 缓存的读取,主要借助get方法
	 */
	public void getCacheBitmap() {
		try {  
			String key = hashKeyForDisk(imageUrl);  
			DiskLruCache.Snapshot snapShot = lruCache.get(key);  
			if (snapShot != null) {  
				InputStream is = snapShot.getInputStream(0);  
				Bitmap bitmap = BitmapFactory.decodeStream(is);  
				img.setImageBitmap(bitmap);
			}  
		} catch (IOException e) {  
			e.printStackTrace();  
		}  
	}

	/*
	 * 根据传入的url下载一张图片,并且将图片写入本地
	 */
	private boolean downUrlToStream(String url,OutputStream outputStream) {
		HttpURLConnection httpurlcon = null ;
		BufferedInputStream in  = null ;
		BufferedOutputStream out = null ;
		URL mUrl;
		try {
			mUrl = new URL(url);
			httpurlcon = (HttpURLConnection)mUrl.openConnection() ;
			in = new BufferedInputStream(httpurlcon.getInputStream(),8*1024) ;
			out = new BufferedOutputStream(outputStream,1024*8) ;
			int b ;
			while((b = in.read()) != -1) {
				out.write(b);
			}
			return true ;
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (final IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			if(httpurlcon != null) {
				httpurlcon.disconnect();
			}
			try {
				if(in != null)
					in.close();
				if(out != null) {
					out.close();
				}
			}catch(IOException e) {
				e.printStackTrace();
			}
		}
		return false ;
	}

	/*
	 * 调用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 ;
	}

	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();  
	}  




	/*
	 * 用以获取cache目录,处理当内存卡有异常(如不在或者不可用)
	 */
	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);
	}


	/*
	 * 得到应用程序的版本号,作为参数传入DiskLruCache的open方法,DiskLruCache默认
	 * 程序版本号发生变化时移除全部缓存数据
	 */
	public int getAppVersion(Context context) {
		PackageInfo version;
		try {
			version = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
			return version.versionCode ;
		} catch (NameNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return 1 ;        //程序发生异常时返回初始版本号1.0
	}


	@Override
	protected void onPause() {
		// TODO Auto-generated method stub
		try {
			lruCache.flush();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		super.onPause();
	}

	@Override
	protected void onDestroy() {
		// TODO Auto-generated method stub
		try {
			lruCache.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		super.onDestroy();
	}
}

最后不要忘了声明权限

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



郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。