從上一篇文章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