麥洛開(kāi)通博客以來(lái),有一段時(shí)間沒(méi)有更新博文了.主要是麥洛這段時(shí)間因項(xiàng)目開(kāi)發(fā)實(shí)在太忙了.今天周六還在公司加班,苦逼程序猿都是這樣生活的.
在呼蘭等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、外貿(mào)網(wǎng)站建設(shè) 網(wǎng)站設(shè)計(jì)制作按需開(kāi)發(fā),公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),成都品牌網(wǎng)站建設(shè),成都全網(wǎng)營(yíng)銷(xiāo)推廣,外貿(mào)網(wǎng)站制作,呼蘭網(wǎng)站建設(shè)費(fèi)用合理。
今天在做項(xiàng)目的時(shí)候,有一個(gè)實(shí)現(xiàn)異步加載圖片的功能,雖然比較簡(jiǎn)單但還是記錄一下吧.因?yàn)辂溌逯皩?shí)現(xiàn)異步加載圖片都是使用了AsynTask這個(gè)API,繼續(xù)這個(gè)類(lèi),實(shí)現(xiàn)起來(lái)非常簡(jiǎn)單也很方便.在doInBackground()方法里實(shí)現(xiàn)下載邏輯.具體實(shí)現(xiàn)如下
實(shí)現(xiàn)邏輯是:先從內(nèi)存中讀取,如果內(nèi)存中有這張圖片,則直接使用;如果內(nèi)存沒(méi)有再到sdcard上讀取,如果有則顯示;如果sdcard上還沒(méi)有則到網(wǎng)絡(luò)上讀取.內(nèi)存中開(kāi)啟緩存是參考了網(wǎng)上的實(shí)現(xiàn).麥洛在這里非常感謝喜歡分享的程序猿們.
public class ImageDownloader extends AsyncTask{ private static final String TAG = "ImageDownloader"; // 為了加快速度,在內(nèi)存中開(kāi)啟緩存(主要應(yīng)用于重復(fù)圖片較多時(shí),或者同一個(gè)圖片要多次被訪問(wèn),比如在ListView時(shí)來(lái)回滾動(dòng)) private Map > imageCache = new HashMap >(); /** * 顯示圖片的控件 */ private ImageView mImageView; public ImageDownloader(ImageView image) { mImageView = image; } @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected Object doInBackground(String... params) { // Log.i("ImageDownloader", "loading image..."); String url = params[0]; Drawable drawable = null; try { if (!"".equals(url) && url != null) { String fileName = url.hashCode()+".jpg"; // 如果緩存過(guò)就從緩存中取出數(shù)據(jù) if (imageCache.containsKey(fileName)) { SoftReference softReference = imageCache.get(fileName); drawable = softReference.get(); if (drawable != null) { return drawable; } } File dir = new File(FileConstant.IMAGE_FILE_PATH); if (!dir.exists()) { boolean m = dir.mkdirs(); } File file = new File(dir, fileName); if (file.exists() && file.length() > 0) { Log.i(TAG, "load image from sd card"); // 如果文件存在則直接讀取sdcard drawable = readFromSdcard(file); } else { //file.createNewFile(); Log.i(TAG, "load image from network"); URL imageUrl = new URL(url); // 寫(xiě)入sdcard if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { saveImageFile(imageUrl, file); drawable = Drawable.createFromStream(new FileInputStream(file), fileName); }else{ //直接從流讀取 drawable = Drawable.createFromStream(imageUrl.openStream(), fileName); } } if(drawable!=null){ //保存在緩存中 imageCache.put(fileName, new SoftReference (drawable)); } } } catch (Exception e) { e.printStackTrace(); } return drawable; } /** * save image */ private void saveImageFile(URL url, File file) { FileOutputStream out = null; InputStream in = null; try { file.deleteOnExit(); out = new FileOutputStream(file); in = url.openStream(); byte[] buf = new byte[1024]; int len = -1; while((len = in.read(buf))!=-1){ out.write(buf, 0, len); out.flush(); } } catch (Exception e) { e.printStackTrace(); } finally { if(out!=null){ try { out.close(); } catch (IOException e) { e.printStackTrace(); } } if(in!=null){ try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 從sdcard中獲取圖片 */ private Drawable readFromSdcard(File file) throws Exception { FileInputStream in = new FileInputStream(file); return Drawable.createFromStream(in, file.getName()); } @Override protected void onPostExecute(Object result) { super.onPostExecute(result); Drawable drawable = (Drawable) result; if (mImageView != null && drawable != null) { mImageView.setBackgroundDrawable(drawable); } } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); } @Override protected void onCancelled() { super.onCancelled(); } }
使用時(shí):
ImageDownloader loader = new ImageDownloader(imageView); loader.execute(url);
其實(shí)這樣的話,還有一些隱患的,就是說(shuō)這個(gè)類(lèi)實(shí)現(xiàn)還是有些問(wèn)題的.比如每次都在imageView中設(shè)置網(wǎng)絡(luò)上的圖片時(shí),其實(shí)是沒(méi)有使用到這個(gè)類(lèi)里面的內(nèi)存緩存的,就是imageCache
Map
因?yàn)槊看卧O(shè)置imageView的時(shí)候,都是new了一個(gè)ImageDownloader的對(duì)象.所以每個(gè)ImageDownloader對(duì)象里面都是獨(dú)立的一個(gè)imageCache.
另外,AsynTask也是一個(gè)線程.而每次使用都開(kāi)一個(gè)線程來(lái)load 圖片,對(duì)線程個(gè)數(shù)沒(méi)有進(jìn)行顯示,畢竟線程數(shù)目還是有限制的.
所以麥洛今天發(fā)現(xiàn)了這個(gè)問(wèn)題,于是參考了別人的實(shí)現(xiàn),使用了線程池,實(shí)現(xiàn)邏輯也上面的代碼一樣,先從內(nèi)存讀取,如果沒(méi)有到sdcard讀取,如果還是沒(méi)有,則是網(wǎng)絡(luò)讀取;實(shí)現(xiàn)沒(méi)有使用AsynTask,具體代碼如下:
/** * 異步加載圖片,并將圖片設(shè)置到ImageView控件中 */ public class ImageDownloader extends AsyncTask{ private static final String TAG = "ImageDownloader"; // 為了加快速度,在內(nèi)存中開(kāi)啟緩存(主要應(yīng)用于重復(fù)圖片較多時(shí),或者同一個(gè)圖片要多次被訪問(wèn),比如在ListView時(shí)來(lái)回滾動(dòng)) private Map > imageCache = new HashMap >(); /** * 顯示圖片的控件 */ private ImageView mImageView; public ImageDownloader(ImageView image) { mImageView = image; } @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected Object doInBackground(String... params) { // Log.i("ImageDownloader", "loading image..."); String url = params[0]; Drawable drawable = null; try { if (!"".equals(url) && url != null) { String fileName = url.hashCode()+".jpg"; // 如果緩存過(guò)就從緩存中取出數(shù)據(jù) if (imageCache.containsKey(fileName)) { SoftReference softReference = imageCache.get(fileName); drawable = softReference.get(); if (drawable != null) { return drawable; } } File dir = new File(FileConstant.IMAGE_FILE_PATH); if (!dir.exists()) { boolean m = dir.mkdirs(); } File file = new File(dir, fileName); if (file.exists() && file.length() > 0) { Log.i(TAG, "load image from sd card"); // 如果文件存在則直接讀取sdcard drawable = readFromSdcard(file); } else { //file.createNewFile(); Log.i(TAG, "load image from network"); URL imageUrl = new URL(url); // 寫(xiě)入sdcard if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { saveImageFile(imageUrl, file); drawable = Drawable.createFromStream(new FileInputStream(file), fileName); }else{ //直接從流讀取 drawable = Drawable.createFromStream(imageUrl.openStream(), fileName); } } if(drawable!=null){ //保存在緩存中 imageCache.put(fileName, new SoftReference (drawable)); } } } catch (Exception e) { e.printStackTrace(); } return drawable; } /** * save image */ private void saveImageFile(URL url, File file) { FileOutputStream out = null; InputStream in = null; try { file.deleteOnExit(); out = new FileOutputStream(file); in = url.openStream(); byte[] buf = new byte[1024]; int len = -1; while((len = in.read(buf))!=-1){ out.write(buf, 0, len); out.flush(); } } catch (Exception e) { e.printStackTrace(); } finally { if(out!=null){ try { out.close(); } catch (IOException e) { e.printStackTrace(); } } if(in!=null){ try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } } /** * 從sdcard中獲取圖片 */ private Drawable readFromSdcard(File file) throws Exception { FileInputStream in = new FileInputStream(file); return Drawable.createFromStream(in, file.getName()); } @Override protected void onPostExecute(Object result) { super.onPostExecute(result); Drawable drawable = (Drawable) result; if (mImageView != null && drawable != null) { mImageView.setBackgroundDrawable(drawable); } } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); } @Override protected void onCancelled() { super.onCancelled(); } }
這個(gè)ImageDownloader2的使用也很簡(jiǎn)單
public class ImageUtil { /** * image loader */ static ImageDownloader2 loader = null; /** * load image */ public static void loadImage(String url,final ImageView imageView){ if(loader == null){ loader = new ImageDownloader2(); } loader.loadDrawable(url, new ImageCallback() { @Override public void imageLoaded(Drawable imageDrawable) { if(imageDrawable!=null){ imageView.setBackgroundDrawable(imageDrawable); } } }); } }
每次在使用是需要調(diào)用ImageUtil.loadImage(url,imageView)將圖片url已經(jīng)需要顯示圖片的控件ImageView的引用傳入就可以了.
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。