点击下载源代码
想起刚開始写代码的时候,领导叫我写一个头像下载的方法,当时屁颠屁颠就写了一个图片下载的,每次都要去网络上请求,最后直接被pass掉了
当时的思路是这种
后来渐渐地就知道了有二级缓存这东西。
自己也阅读过非常多关于双缓存的文章。
APP开发到越后面。对性能的要求越高。那么双缓存的优势就逐渐体现出来了。
所谓图片双缓存。首先到执行内存中请求,再到sd卡请求,最后到网络请求,流程图例如以下
那我们从第一部開始解析
1.先看 内存缓存的代码
-
public class MemoryCache implements ImageCache {
-
private static final String TAG = MemoryCache.class.getSimpleName();
-
private LruCache<String,Bitmap> mMemoryCache;
-
public MemoryCache(){
-
init();
-
}
-
-
private void init(){
-
final int maxMemory = (int) (Runtime.getRuntime().maxMemory()/1024);
-
final int cacheSize = maxMemory/4;
-
mMemoryCache = new LruCache<String,Bitmap>(cacheSize){
-
@Override
-
protected int sizeOf(String key, Bitmap value) {
-
return value.getRowBytes()*value.getHeight()/1024;
-
}
-
};
-
}
-
@Override
-
public Bitmap get(String key) {
-
Bitmap bitmap = mMemoryCache.get(key);
-
if (bitmap!=null){
-
Log.i(TAG,"File is exist in memory");
-
}
-
return mMemoryCache.get(key);
-
}
-
-
@Override
-
public void put(String key, Bitmap bitmap) {
-
if (get(key)==null) {
-
mMemoryCache.put(key, bitmap);
-
}
-
}
-
}
init()方法中对一些变量进行初始化,mMemoryCache用于在内存中缓存图片
-
public Bitmap get(String key) {}
get()方法用于从内存中获得缓存
-
public void put(String key, Bitmap bitmap) {}
put()方法将下载好的图片缓存到内存中,方便下次使用
2.再看sd卡缓存
-
public class DiskCache implements ImageCache {
-
private static final String TAG = DiskCache.class.getSimpleName();
-
static String mPath ;
-
public DiskCache(Context context){
-
init(context);
-
}
-
private void init(Context context){
-
-
mPath = getDiskCachePath(context,"bitmap");
-
File cacheDir = new File(mPath);
-
if (!cacheDir.exists()) {
-
cacheDir.mkdirs();
-
}
-
}
-
@Override
-
public Bitmap get(String key) {
-
File file = new File(mPath+key);
-
if (file.exists()){
-
return BitmapFactory.decodeFile(mPath+key);
-
}
-
return null;
-
}
-
-
@Override
-
public void put(String key, Bitmap bitmap) {
-
FileOutputStream fileOutputStream = null;
-
try {
-
File file = new File(mPath+key);
-
if (file.exists()){
-
Log.i(TAG,"File is exist on disk");
-
}
-
fileOutputStream = new FileOutputStream(mPath+key);
-
bitmap.compress(Bitmap.CompressFormat.PNG,100,fileOutputStream);
-
-
} catch (FileNotFoundException e) {
-
e.printStackTrace();
-
}finally {
-
CloseUtils.closeQuietly(fileOutputStream);
-
}
-
}
-
-
-
-
-
-
-
-
public String getDiskCachePath(Context context, String dir) {
-
String cachePath;
-
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())
-
|| !Environment.isExternalStorageRemovable()) {
-
cachePath = context.getExternalCacheDir().getPath();
-
} else {
-
cachePath = context.getCacheDir().getPath();
-
}
-
return cachePath + File.separator + dir;
-
}
-
-
}
相同
init()方法中对一些变量进行初始化,mMemoryCache用于在内存中缓存图片
-
public Bitmap get(String key) {}
get()方法用于从内存中获得缓存
-
public void put(String key, Bitmap bitmap) {}
put()方法将下载好的图片缓存到内存中,方便下次使用
接下来我们会在一个叫DoubleCache的类中对以上两种缓存方式进行管理
-
public class DoubleCache implements ImageCache {
-
private static final String TAG = DoubleCache.class.getSimpleName();
-
private MemoryCache mMemoryCache = null;
-
private DiskCache mDiskCache = null;
-
-
public DoubleCache(Context context){
-
mMemoryCache = new MemoryCache();
-
mDiskCache = new DiskCache(context);
-
}
-
@Override
-
public Bitmap get(String url) {
-
String key = url2Key(url);
-
Bitmap bitmap = mMemoryCache.get(key);
-
if(bitmap==null){
-
bitmap = mDiskCache.get(key);
-
}else {
-
}
-
return bitmap;
-
}
-
-
@Override
-
public void put(String url, Bitmap bitmap) {
-
String key = url2Key(url);
-
mMemoryCache.put(key,bitmap);
-
mDiskCache.put(key,bitmap);
-
}
-
-
-
private String url2Key(String url){
-
String key = MD5.hashKeyForDisk(url)+".jpg";
-
return key;
-
}
-
}
我们在获取缓存的时候先从内存中获取。当内存中击中直接返回,当内存中没有击中,则訪问sd卡。
3.看到这里,小伙伴们一定急了,这仅仅有从缓存中和sd卡中取图片,并没有从网络获取,别急。立即就来
-
public class ImageLoader {
-
private static final String TAG = ImageLoader.class.getSimpleName();
-
-
private static ImageLoader sInstance;
-
-
private DoubleCache mDoubleCache = null;
-
-
private ExecutorService mExecutorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
-
-
private ImageLoader(Context context) {
-
mDoubleCache = new DoubleCache(context);
-
}
-
-
public static ImageLoader getInstance(Context context) {
-
if (sInstance == null) {
-
synchronized (ImageLoader.class) {
-
sInstance = new ImageLoader(context);
-
}
-
}
-
return sInstance;
-
}
-
-
public void displayImage(String url, ImageView imageView) {
-
Bitmap bitmap = mDoubleCache.get(url);
-
if (bitmap != null) {
-
imageView.setImageBitmap(bitmap);
-
mDoubleCache.put(url,bitmap);
-
return;
-
}
-
submitLoadRequest(url, imageView);
-
}
-
-
private void submitLoadRequest(final String url, final ImageView imageView) {
-
Log.i(TAG,"Download,url:"+url);
-
imageView.setTag(url);
-
mExecutorService.submit(new Runnable() {
-
@Override
-
public void run() {
-
final Bitmap bitmap = downloadImage(url);
-
if (imageView.getTag().equals(url)) {
-
-
imageView.post(new Runnable() {
-
@Override
-
public void run() {
-
imageView.setImageBitmap(bitmap);
-
}
-
});
-
}
-
mDoubleCache.put(url, bitmap);
-
}
-
});
-
}
-
Handler handler = new Handler(){
-
@Override
-
public void handleMessage(Message msg) {
-
-
}
-
};
-
-
public Bitmap downloadImage(String url) {
-
Bitmap bitmap = null;
-
HttpURLConnection conn = null;
-
try {
-
URL url1 = new URL(url);
-
conn = (HttpURLConnection) url1.openConnection();
-
bitmap = BitmapFactory.decodeStream(conn.getInputStream());
-
if (bitmap!=null){
-
mDoubleCache.put(url,bitmap);
-
}
-
} catch (MalformedURLException e) {
-
e.printStackTrace();
-
} catch (Exception e) {
-
e.printStackTrace();
-
} finally {
-
if (conn != null) {
-
conn.disconnect();
-
}
-
}
-
return bitmap;
-
}
从
方法中能够看到。假设缓存中都没有才从网络中获取
-
public Bitmap downloadImage(String url) {}
下载完毕之后。把图片放到缓存中。
到这里,我们的第二张流程图就走完了。是不是非常easy。
我们在看一下是怎样使用的
-
private ImageView imageView;
-
private ImageView imageView2;
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.activity_main);
-
imageView = (ImageView) findViewById(R.id.image);
-
imageView2 = (ImageView) findViewById(R.id.image2);
-
imageView.setOnClickListener(new View.OnClickListener() {
-
@Override
-
public void onClick(View v) {
-
-
ImageLoader.getInstance(MainActivity.this).displayImage("http://img.my.csdn.net/uploads/201407/26/1406383299_1976.jpg", imageView);
-
}
-
});
-
imageView2.setOnClickListener(new View.OnClickListener() {
-
@Override
-
public void onClick(View v) {
-
-
ImageLoader.getInstance(MainActivity.this).displayImage("http://img.my.csdn.net/uploads/201407/26/1406383299_1976.jpg", imageView2);
-
}
-
});
-
}
点击下载源代码