Android LruCache圖片緩存使用(二)

從上一篇文章LruCache的源碼簡介中,我想我們可以知道LruCache的基本實現原理了!如果沒有了解的可以先看看LruCache的基本介紹

那在實際開發中我們如何使用LruCache呢?

首先,我們要覆寫sizeof這個方法。如下:

int maxCache = (int) (Runtime.getRuntime().maxMemory() / 1024);//得到應用的最大可用內存
        int cacheSize = maxCache / 8; //一般情況下最多爲可用內存的1/8
        mLruCache = new LruCache<String,Bitmap>(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<String, Bitmap> mLruCache;//所有圖片緩存
    private List<DownloadAsyncTask> 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<LruCacheImgAdapter.DownloadAsyncTask>();
        initLruCache();
    }

    private void initLruCache(){
        int maxCache = (int) (Runtime.getRuntime().maxMemory() / 1024);//得到應用的最大可用內存
        int cacheSize = maxCache / 8; //一般情況下最多爲可用內存的1/8
        mLruCache = new LruCache<String,Bitmap>(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<String,Void,Bitmap>{

        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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章