Android LruCache图片缓存使用(二)

从上一篇文章LruCache的源码简介中,我想我们可以知道LruCache的基本实现原理了!如果没有了解的可以先看看LruCache的基本介绍。

那在实际开发中我们如何使用LruCache呢?

首先,我们要覆写sizeof这个方法。如下:

int maxCache = (int) (Runtime.getRuntime().maxMemory() / 1024);//得到应用的最大可用内存
        int cacheSize = maxCache / 8; //一般情况下最多为可用内存的1/8
        mLruCache = new LruCache(cacheSize){
            @Override
            protected int sizeOf(String key, Bitmap value) {
                if(value != null)
                    return value.getByteCount() / 1024;
                return 0;
            }
        };

然后,检查LruCache的缓存中是否有对应的key值,如果有就返回对应的Bitmap,如果没有则开异步线程去下载图片后再存入LruCache。其中核心代码如下:

    /**
     * 通过key值从LruCache中获取缓存对象
     * 
     * @param key
     * @return 如果LruCache存在该key则返回缓存的bitmap,否则返回null
     */
    private Bitmap getBitmapFromCache(String key){
        return mLruCache.get(key);
    }

    /**
     * 通过key将Bitmap缓存到LruCache中
     * 
     * @param key
     * @param bitmap
     */
    private void putBitmapToCache(String key, Bitmap bitmap){
        if(getBitmapFromCache(key) == null && bitmap != null)
            mLruCache.put(key, bitmap);
    }

下面我们直接来看一个简单的demo

MainActivity:

package com.richardli.lrucachedemo_1;

import android.app.Activity;
import android.os.Bundle;
import android.widget.GridView;

public class MainActivity extends Activity {

    private GridView mGridView;
    private LruCacheImgAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        init();
    }

    private void init(){
        mGridView = (GridView) findViewById(R.id.imgsGridView);
        mAdapter = new LruCacheImgAdapter(this, imageThumbUrls ,mGridView);
        mGridView.setAdapter(mAdapter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mAdapter.cancelAllDowanTask();
        mAdapter.clearAllCache();
        mAdapter = null;
        System.gc();
    }

    /**
     * 图片资源从郭神博客中抠出来的,呵呵...
     */
    public final static String[] imageThumbUrls = new String[] {  
        "https://img-my.csdn.net/uploads/201407/26/1406383299_1976.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383291_6518.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383291_8239.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383290_9329.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383290_1042.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383275_3977.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383265_8550.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383264_3954.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383264_4787.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383264_8243.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383248_3693.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383243_5120.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383242_3127.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383242_9576.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383242_1721.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383219_5806.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383214_7794.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383213_4418.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383213_3557.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383210_8779.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383172_4577.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383166_3407.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383166_2224.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383166_7301.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383165_7197.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383150_8410.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383131_3736.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383130_5094.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383130_7393.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383129_8813.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383100_3554.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383093_7894.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383092_2432.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383092_3071.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383091_3119.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383059_6589.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383059_8814.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383059_2237.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383058_4330.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406383038_3602.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382942_3079.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382942_8125.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382942_4881.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382941_4559.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382941_3845.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382924_8955.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382923_2141.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382923_8437.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382922_6166.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382922_4843.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382905_5804.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382904_3362.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382904_2312.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382904_4960.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382900_2418.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382881_4490.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382881_5935.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382880_3865.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382880_4662.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382879_2553.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382862_5375.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382862_1748.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382861_7618.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382861_8606.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382861_8949.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382841_9821.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382840_6603.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382840_2405.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382840_6354.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382839_5779.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382810_7578.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382810_2436.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382809_3883.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382809_6269.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382808_4179.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382790_8326.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382789_7174.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382789_5170.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382789_4118.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382788_9532.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382767_3184.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382767_4772.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382766_4924.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382766_5762.jpg",  
        "https://img-my.csdn.net/uploads/201407/26/1406382765_7341.jpg"  
    };  

}

LruCacheImgAdapter适配器:

package com.richardli.lrucachedemo_1;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.HttpsURLConnection;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.support.v4.util.LruCache;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;

public class LruCacheImgAdapter extends BaseAdapter implements OnScrollListener{

    private Context mContext;
    private LayoutInflater mInflater;

    private String[] mImgsList;
    private GridView mGridView;
    private LruCache mLruCache;//所有图片缓存
    private List mDownloadTastAllList; //所有异步下载集合

    private int mFirstVisibleItem;//当前可见列表的第一项
    private int mVisibleItemCount;//当前可见表项个数
    private boolean isFirstCome = true;// 是否是第一次进入加载

    public LruCacheImgAdapter(Context ctx , String[] imgs , GridView mGridView){
        this.mContext = ctx;
        this.mImgsList = imgs;
        this.mGridView = mGridView;
        this.mGridView.setOnScrollListener(this);
        mInflater = LayoutInflater.from(mContext);
        mDownloadTastAllList = new ArrayList();
        initLruCache();
    }

    private void initLruCache(){
        int maxCache = (int) (Runtime.getRuntime().maxMemory() / 1024);//得到应用的最大可用内存
        int cacheSize = maxCache / 8; //一般情况下最多为可用内存的1/8
        mLruCache = new LruCache(cacheSize){
            @Override
            protected int sizeOf(String key, Bitmap value) {
                if(value != null)
                    return value.getByteCount() / 1024;
                return 0;
            }
        };
    }

    @Override
    public int getCount() {
        return mImgsList.length;
    }

    @Override
    public Object getItem(int position) {
        return mImgsList[position];
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder mViewHolder = null;
        if(convertView == null){
            convertView = mInflater.inflate(R.layout.img_grid_item_layout, parent , false);
            mViewHolder = new ViewHolder();
            mViewHolder.mImagsView = (ImageView) convertView.findViewById(R.id.img_show_iv);
            convertView.setTag(mViewHolder);
        }else{
            mViewHolder = (ViewHolder) convertView.getTag();
        }

        String url = mImgsList[position];

        mViewHolder.mImagsView.setTag(url);
        displayImage(url , mViewHolder.mImagsView);

        return convertView;
    }

    private static class ViewHolder{
        ImageView mImagsView;
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        if(scrollState == SCROLL_STATE_IDLE)
            loadBitmap(mFirstVisibleItem, mVisibleItemCount);
        else
            cancelAllDowanTask();
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
        mFirstVisibleItem = firstVisibleItem;
        mVisibleItemCount = visibleItemCount;
        if(isFirstCome && visibleItemCount > 0){
            isFirstCome = false;
            loadBitmap(mFirstVisibleItem, mVisibleItemCount);
        }
    }


    private void displayImage(String url, ImageView imgView){
        Bitmap mCacheBtimap = getBitmapFromCache(url);
        if(mCacheBtimap != null)
            imgView.setImageBitmap(mCacheBtimap);
        else
            imgView.setBackgroundResource(android.R.color.holo_orange_dark);
    }

    private void loadBitmap(int mFirstVisibleItem, int mVisibleItemCount){
        for(int i = mFirstVisibleItem ; i < mFirstVisibleItem + mVisibleItemCount ; i++){
            String url = mImgsList[i];
            // 判断图片是否存在缓存中,如果存在则不下载。
            Bitmap bitmap = getBitmapFromCache(url);
            if(bitmap != null){
                ImageView imgView = (ImageView) mGridView.findViewWithTag(url);
                if(imgView != null)
                    imgView.setImageBitmap(bitmap);
            }else{
                //开启异步任务下载图片
                DownloadAsyncTask downTask = new DownloadAsyncTask();
                mDownloadTastAllList.add(downTask);
                downTask.execute(url);
            }
        }
    }

    /**
     * 通过key值从LruCache中获取缓存对象
     * 
     * @param key
     * @return 如果LruCache存在该key则返回缓存的bitmap,否则返回null
     */
    private Bitmap getBitmapFromCache(String key){
        return mLruCache.get(key);
    }

    /**
     * 通过key将Bitmap缓存到LruCache中
     * 
     * @param key
     * @param bitmap
     */
    private void putBitmapToCache(String key, Bitmap bitmap){
        if(getBitmapFromCache(key) == null && bitmap != null)
            mLruCache.put(key, bitmap);
    }

    /**
     * 清除所有缓存
     */
    public void clearAllCache(){
        if(mLruCache != null){
            if(mLruCache.size() > 0)
                mLruCache.evictAll();
            mLruCache = null;
        }
    }

    /**
     * 通过url异步下载图片,下载成功后保存至缓存中,并显示
     * @author Rrichard
     *
     */
    class DownloadAsyncTask extends AsyncTask{

        private String imgUrl ;

        @Override
        protected Bitmap doInBackground(String... params) {
            imgUrl = params[0];
            Bitmap bitmap = getBitmapForUrl(imgUrl);
            if(bitmap != null)
                putBitmapToCache(imgUrl , bitmap);
            return bitmap;
        }

        @Override
        protected void onPostExecute(Bitmap result) {
            super.onPostExecute(result);
            ImageView mImageView = (ImageView) mGridView.findViewWithTag(imgUrl);
            if(mImageView != null && result != null){
                mImageView.setImageBitmap(result);
                mDownloadTastAllList.remove(this);
            }
        }

    }

    /**
     * 取消所有下载任务
     */
    public void cancelAllDowanTask(){
        if(mDownloadTastAllList != null && mDownloadTastAllList.size() != 0){
            for(DownloadAsyncTask task : mDownloadTastAllList)
                task.cancel(true);
        }
    }

    /**
     * 通过URL下载图片
     * 
     * @param url
     * @return
     */
    private Bitmap getBitmapForUrl(String url){
        Bitmap bitmap = null;
        HttpURLConnection connection = null;
        try {
            URL mUrl = new URL(url);
            connection = (HttpURLConnection) mUrl.openConnection();
            connection.setConnectTimeout(10 * 1000);
            connection.setReadTimeout(10 * 1000);
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.connect();
            if(connection.getResponseCode() == HttpsURLConnection.HTTP_OK)
                bitmap = BitmapFactory.decodeStream(connection.getInputStream());
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            if(connection != null){
                connection.disconnect();
                connection = null;
            }
        }
        return bitmap;
    }

}

效果图用应用宝编辑的,搞得不是很好。不要介意,将就着看

到这里就是一个简单的LruCache图片缓存的使用,但是,在实际开发中我们肯定不能像上面这样使用。因为很明显嘛,上面的代码有很多问题。比如:下载图片时,一个个下载这效率特低了吧!而且很容易出现异常。图片下载下来,图片太大了会出现OOM,因为图片没有压缩采样处理。所以,我们先就图片的处理来进行一下简单的修改。

/**
     * 通过URL下载图片
     * 
     * @param url
     * @return
     */
    private Bitmap getBitmapForUrl(String url){
        Bitmap bitmap = null;
        HttpURLConnection connection = null;
        try {
            URL mUrl = new URL(url);
            connection = (HttpURLConnection) mUrl.openConnection();
            connection.setConnectTimeout(10 * 1000);
            connection.setReadTimeout(10 * 1000);
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.connect();
            if(connection.getResponseCode() == HttpsURLConnection.HTTP_OK){
                InputStream inputStream = connection.getInputStream();
                ByteArrayOutputStream outStream = new ByteArrayOutputStream();      
                byte[] buffer = new byte[1024];      
                int len = 0;      
                while( (len=inputStream.read(buffer)) != -1){      
                    outStream.write(buffer, 0, len);      
                }      
                outStream.close();      
                inputStream.close();      
                byte[] data = outStream.toByteArray();
                if(data != null){
                    // 进行采样压缩图片
                    BitmapFactory.Options options = new BitmapFactory.Options();
                    options.inJustDecodeBounds = true;
                    BitmapFactory.decodeByteArray(data, 0, data.length , options);
                    int height = options.outHeight;
                    int width = options.outWidth;
                    int inSampleSize = 1;
                    if(height > 150 || width > 150){
                        int heightSize = Math.round(height / 80);
                        int widthSize = Math.round(width / 80);
                        inSampleSize = heightSize >= widthSize ? widthSize : heightSize;
                    }
                    options.inSampleSize = inSampleSize;
                    options.inJustDecodeBounds = false;
                    bitmap = BitmapFactory.decodeByteArray(data, 0, data.length , options);;
                }
            }
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally{
            if(connection != null){
                connection.disconnect();
                connection = null;
            }
        }
        return bitmap;
    }

当然这代码也不是写得很好,只是举个简单的例子。实际开发中肯定不能这样做,得剥离出来,进行优化。所以后面的就留到下一篇博客在写吧!

Demo下载地址:http://download.csdn.net/detail/richardli1228/9296797

你可能感兴趣的:(Android学习开发)