成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Android遠(yuǎn)程圖片獲取和本地緩存

移動(dòng)開發(fā) Android
對(duì)于客戶端——服務(wù)器端應(yīng)用,從遠(yuǎn)程獲取圖片算是經(jīng)常要用的一個(gè)功能,而圖片資源往往會(huì)消耗比較大的流量,對(duì)應(yīng)用來說,如果處理不好這個(gè)問題,那會(huì)讓用戶很崩潰,不知不覺手機(jī)流量就用完了,等用戶發(fā)現(xiàn)是你的應(yīng)用消耗掉了他手機(jī)流量的話,那么可想而知你的應(yīng)用將面臨什么樣的命運(yùn)。

另外一個(gè)問題就是加載速度,如果應(yīng)用中圖片加載速度很慢的話,那么用戶同樣會(huì)等到崩潰。

那么如何處理好圖片資源的獲取和管理呢?

異步下載

本地緩存

異步下載

大家都知道,在android應(yīng)用中UI線程5秒沒響應(yīng)的話就會(huì)拋出無響應(yīng)異常,對(duì)于遠(yuǎn)程獲取大的資源來說,這種異常還是很容易就會(huì)拋出來的,那么怎么避免這種問題的產(chǎn)生。在android中提供兩種方法來做這件事情:

啟動(dòng)一個(gè)新的線程來獲取資源,完成后通過Handler機(jī)制發(fā)送消息,并在UI線程中處理消息,從而達(dá)到在異步線程中獲取圖片,然后通過Handler Message來更新UI線程的過程。

使用android中提供的AsyncTask來完成。

 

具體的做法這里就不介紹了,查下API就可以了,或者是google、baidu下。這里主要來說本地緩存。

本地緩存

對(duì)于圖片資源來說,你不可能讓應(yīng)用每次獲取的時(shí)候都重新到遠(yuǎn)程去下載(ListView),這樣會(huì)浪費(fèi)資源,但是你又不能讓所有圖片資源都放到內(nèi)存中去(雖然這樣加載會(huì)比較快),因?yàn)閳D片資源往往會(huì)占用很大的內(nèi)存空間,容易導(dǎo)致OOM。那么如果下載下來的圖片保存到SDCard中,下次直接從SDCard上去獲取呢?這也是一種做法,我看了下,還是有不少應(yīng)用采用這種方式的。采用LRU等一些算法可以保證sdcard被占用的空間只有一小部分,這樣既保證了圖片的加載、節(jié)省了流量、又使SDCard的空間只占用了一小部分。另外一種做法是資源直接保存在內(nèi)存中,然后設(shè)置過期時(shí)間和LRU規(guī)則。

sdcard保存:

 

在sdcard上開辟一定的空間,需要先判斷sdcard上剩余空間是否足夠,如果足夠的話就可以開辟一些空間,比如10M

當(dāng)需要獲取圖片時(shí),就先從sdcard上的目錄中去找,如果找到的話,使用該圖片,并更新圖片***被使用的時(shí)間。如果找不到,通過URL去download

去服務(wù)器端下載圖片,如果下載成功了,放入到sdcard上,并使用,如果失敗了,應(yīng)該有重試機(jī)制。比如3次。

下載成功后保存到sdcard上,需要先判斷10M空間是否已經(jīng)用完,如果沒有用完就保存,如果空間不足就根據(jù)LRU規(guī)則刪除一些最近沒有被用戶的資源。

關(guān)鍵代碼:

保存圖片到SD卡上

  1. private void saveBmpToSd(Bitmap bm, Stringurl) { 
  2.         if (bm == null) { 
  3.             Log.w(TAG, " trying to savenull bitmap"); 
  4.             return; 
  5.         } 
  6.          //判斷sdcard上的空間 
  7.         if (FREE_SD_SPACE_NEEDED_TO_CACHE >freeSpaceOnSd()) { 
  8.             Log.w(TAG, "Low free space onsd, do not cache"); 
  9.             return; 
  10.         } 
  11.         String filename =convertUrlToFileName(url); 
  12.         String dir = getDirectory(filename); 
  13.         File file = new File(dir +"/" + filename); 
  14.         try { 
  15.             file.createNewFile(); 
  16.             OutputStream outStream = newFileOutputStream(file); 
  17.            bm.compress(Bitmap.CompressFormat.JPEG, 100, outStream); 
  18.             outStream.flush(); 
  19.             outStream.close(); 
  20.             Log.i(TAG, "Image saved tosd"); 
  21.         } catch (FileNotFoundException e) { 
  22.             Log.w(TAG,"FileNotFoundException"); 
  23.         } catch (IOException e) { 
  24.             Log.w(TAG,"IOException"); 
  25.         } 
  26.     } 

計(jì)算sdcard上的空間:

  1. /** 
  2.  * 計(jì)算sdcard上的剩余空間 
  3.  * @return 
  4.  */ 
  5. private int freeSpaceOnSd() { 
  6.     StatFs stat = newStatFs(Environment.getExternalStorageDirectory() .getPath()); 
  7.     double sdFreeMB = ((double)stat.getAvailableBlocks() * (double) stat.getBlockSize()) / MB; 
  8.     return (int) sdFreeMB; 

修改文件的***修改時(shí)間

  1. /** 
  2.  * 修改文件的***修改時(shí)間 
  3.  * @param dir 
  4.  * @param fileName 
  5.  */ 
  6. private void updateFileTime(String dir,String fileName) { 
  7.     File file = new File(dir,fileName);        
  8.     long newModifiedTime =System.currentTimeMillis(); 
  9.     file.setLastModified(newModifiedTime); 

本地緩存優(yōu)化

  1. /** 
  2.  *計(jì)算存儲(chǔ)目錄下的文件大小,當(dāng)文件總大小大于規(guī)定的CACHE_SIZE或者sdcard剩余空間小于FREE_SD_SPACE_NEEDED_TO_CACHE的規(guī)定 
  3.  * 那么刪除40%最近沒有被使用的文件 
  4.  * @param dirPath 
  5.  * @param filename 
  6.  */ 
  7. private void removeCache(String dirPath) { 
  8.     File dir = new File(dirPath); 
  9.     File[] files = dir.listFiles(); 
  10.     if (files == null) { 
  11.         return; 
  12.     } 
  13.     int dirSize = 0
  14.     for (int i = 0; i < files.length;i++) { 
  15.         if(files[i].getName().contains(WHOLESALE_CONV)) { 
  16.             dirSize += files[i].length(); 
  17.         } 
  18.     } 
  19.     if (dirSize > CACHE_SIZE * MB ||FREE_SD_SPACE_NEEDED_TO_CACHE > freeSpaceOnSd()) { 
  20.         int removeFactor = (int) ((0.4 *files.length) + 1); 
  21.  
  22.         Arrays.sort(files, newFileLastModifSort()); 
  23.  
  24.         Log.i(TAG, "Clear some expiredcache files "); 
  25.  
  26.         for (int i = 0; i <removeFactor; i++) { 
  27.  
  28.             if(files[i].getName().contains(WHOLESALE_CONV)) { 
  29.  
  30.                 files[i].delete();              
  31.  
  32.             } 
  33.  
  34.         } 
  35.  
  36.     } 
  37.  
  38. /** 
  39.  * 刪除過期文件 
  40.  * @param dirPath 
  41.  * @param filename 
  42.  */ 
  43. private void removeExpiredCache(StringdirPath, String filename) { 
  44.  
  45.     File file = new File(dirPath,filename); 
  46.  
  47.     if (System.currentTimeMillis() -file.lastModified() > mTimeDiff) { 
  48.  
  49.         Log.i(TAG, "Clear some expiredcache files "); 
  50.  
  51.         file.delete(); 
  52.  
  53.     } 
  54.  

文件使用時(shí)間排序

  1. /** 
  2.  * TODO 根據(jù)文件的***修改時(shí)間進(jìn)行排序 * 
  3.  */ 
  4. classFileLastModifSort implements Comparator<File>
  5.     public int compare(File arg0, File arg1) { 
  6.         if (arg0.lastModified() >arg1.lastModified()) { 
  7.             return 1; 
  8.         } else if (arg0.lastModified() ==arg1.lastModified()) { 
  9.             return 0; 
  10.         } else { 
  11.             return -1; 
  12.         } 
  13.     } 

內(nèi)存保存:

在內(nèi)存中保存的話,只能保存一定的量,而不能一直往里面放,需要設(shè)置數(shù)據(jù)的過期時(shí)間、LRU等算法。這里有一個(gè)方法是把常用的數(shù)據(jù)放到一個(gè)緩存中(A),不常用的放到另外一個(gè)緩存中(B)。當(dāng)要獲取數(shù)據(jù)時(shí)先從A中去獲取,如果A中不存在那么再去B中獲取。B中的數(shù)據(jù)主要是A中LRU出來的數(shù)據(jù),這里的內(nèi)存回收主要針對(duì)B內(nèi)存,從而保持A中的數(shù)據(jù)可以有效的被命中。

 

先定義A緩存:

  1. private final HashMap<String, Bitmap>mHardBitmapCache = new LinkedHashMap<String, Bitmap>(HARD_CACHE_CAPACITY/ 2, 0.75f, true) { 
  2.         @Override 
  3.         protected booleanremoveEldestEntry(LinkedHashMap.Entry<String, Bitmap> eldest) { 
  4.             if (size() >HARD_CACHE_CAPACITY) { 
  5.                //當(dāng)map的size大于30時(shí),把最近不常用的key放到mSoftBitmapCache中,從而保證mHardBitmapCache的效率 
  6.                mSoftBitmapCache.put(eldest.getKey(), newSoftReference<Bitmap>(eldest.getValue())); 
  7.                 return true; 
  8.             } else 
  9.                 return false; 
  10.         } 
  11.     }; 

再定于B緩存:

  1. /** 
  2.     *當(dāng)mHardBitmapCache的key大于30的時(shí)候,會(huì)根據(jù)LRU算法把最近沒有被使用的key放入到這個(gè)緩存中。 
  3.     *Bitmap使用了SoftReference,當(dāng)內(nèi)存空間不足時(shí),此cache中的bitmap會(huì)被垃圾回收掉 
  4.     */ 
  5.    private final staticConcurrentHashMap<String, SoftReference<Bitmap>> mSoftBitmapCache =new ConcurrentHashMap<String,SoftReference<Bitmap>>(HARD_CACHE_CAPACITY / 2); 

從緩存中獲取數(shù)據(jù):

  1. /** 
  2.      * 從緩存中獲取圖片 
  3.      */ 
  4.     private Bitmap getBitmapFromCache(Stringurl) { 
  5.         // 先從mHardBitmapCache緩存中獲取 
  6.         synchronized (mHardBitmapCache) { 
  7.             final Bitmap bitmap =mHardBitmapCache.get(url); 
  8.             if (bitmap != null) { 
  9.                 //如果找到的話,把元素移到linkedhashmap的最前面,從而保證在LRU算法中是***被刪除 
  10.                 mHardBitmapCache.remove(url); 
  11.                 mHardBitmapCache.put(url,bitmap); 
  12.                 return bitmap; 
  13.             } 
  14.         } 
  15.         //如果mHardBitmapCache中找不到,到mSoftBitmapCache中找 
  16.         SoftReference<Bitmap>bitmapReference = mSoftBitmapCache.get(url); 
  17.         if (bitmapReference != null) { 
  18.             final Bitmap bitmap =bitmapReference.get(); 
  19.             if (bitmap != null) { 
  20.                 return bitmap; 
  21.             } else { 
  22.                 mSoftBitmapCache.remove(url); 
  23.             } 
  24.         } 
  25.         return null; 
  26.     } 

如果緩存中不存在,那么就只能去服務(wù)器端去下載:

  1. /** 
  2.      * 異步下載圖片 
  3.      */ 
  4.     class ImageDownloaderTask extendsAsyncTask<String, Void, Bitmap> { 
  5.         private static final int IO_BUFFER_SIZE4 * 1024; 
  6.         private String url; 
  7.         private finalWeakReference<ImageView> imageViewReference; 
  8.         public ImageDownloaderTask(ImageViewimageView) { 
  9.             imageViewReference = newWeakReference<ImageView>(imageView); 
  10.         } 
  11.   
  12.        @Override 
  13.         protected BitmapdoInBackground(String... params) { 
  14.             final AndroidHttpClient client =AndroidHttpClient.newInstance("Android"); 
  15.             url = params[0]; 
  16.             final HttpGet getRequest = newHttpGet(url); 
  17.             try { 
  18.                 HttpResponse response =client.execute(getRequest); 
  19.                 final int statusCode =response.getStatusLine().getStatusCode(); 
  20.                 if (statusCode !=HttpStatus.SC_OK) { 
  21.                     Log.w(TAG, "從" +url + "中下載圖片時(shí)出錯(cuò)!,錯(cuò)誤碼:" + statusCode); 
  22.                     return null; 
  23.                 } 
  24.                 final HttpEntity entity =response.getEntity(); 
  25.                 if (entity != null) { 
  26.                     InputStream inputStream =null
  27.                     OutputStream outputStream =null
  28.                     try { 
  29.                         inputStream =entity.getContent(); 
  30.                         finalByteArrayOutputStream dataStream = new ByteArrayOutputStream(); 
  31.                         outputStream = newBufferedOutputStream(dataStream, IO_BUFFER_SIZE); 
  32.                         copy(inputStream,outputStream); 
  33.                         outputStream.flush(); 
  34.                         final byte[] data =dataStream.toByteArray(); 
  35.                         final Bitmap bitmap =BitmapFactory.decodeByteArray(data, 0, data.length); 
  36.                         return bitmap; 
  37.                     } finally { 
  38.                         if (inputStream !=null) { 
  39.                            inputStream.close(); 
  40.                         } 
  41.                         if (outputStream !=null) { 
  42.                            outputStream.close(); 
  43.                         } 
  44.                        entity.consumeContent(); 
  45.                     } 
  46.                 } 
  47.             } catch (IOException e) { 
  48.                 getRequest.abort(); 
  49.                 Log.w(TAG, "I/O errorwhile retrieving bitmap from " + url, e); 
  50.             } catch (IllegalStateException e) { 
  51.                 getRequest.abort(); 
  52.                 Log.w(TAG, "Incorrect URL:" + url); 
  53.             } catch (Exception e) { 
  54.                 getRequest.abort(); 
  55.                 Log.w(TAG, "Error whileretrieving bitmap from " + url, e); 
  56.             } finally { 
  57.                 if (client != null) { 
  58.                     client.close(); 
  59.                 } 
  60.             } 
  61.             return null; 
  62.         } 

這是兩種做法,還有一些應(yīng)用在下載的時(shí)候使用了線程池和消息隊(duì)列MQ,對(duì)于圖片下載的效率要更好一些。有興趣的同學(xué)可以看下。

總結(jié)

對(duì)于遠(yuǎn)程圖片等相對(duì)比較大的資源一定要在異步線程中去獲取本地做緩存

責(zé)任編輯:佚名 來源: blog.csdn
相關(guān)推薦

2023-05-12 11:52:21

緩存場(chǎng)景性能

2014-10-15 14:07:21

AndroidGlide組件

2009-12-10 09:48:26

PHP獲取遠(yuǎn)程圖片

2013-07-03 15:11:41

ANdroid

2010-09-26 10:14:11

JVM監(jiān)控

2011-01-18 13:54:45

2021-09-01 06:48:16

AndroidGlide緩存

2023-11-11 19:43:12

緩存數(shù)據(jù)庫

2019-08-16 10:54:03

本地存儲(chǔ)javascripthttp緩存

2013-09-02 14:58:44

2015-08-25 16:13:18

Windows 10緩存

2024-11-01 16:18:52

2021-03-29 11:51:07

緩存儲(chǔ)存數(shù)據(jù)

2015-06-11 10:12:26

Android圖片加載緩存

2012-05-16 16:06:25

VMwareSSDvSphere 5

2024-04-24 10:24:09

2022-08-11 15:45:13

Git

2013-10-16 16:58:17

iOS優(yōu)化緩存優(yōu)化

2013-04-25 14:02:59

2013-12-13 11:04:36

命令scp
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 国产精品黄色 | 久久精品久久久久久 | 亚洲精品中文字幕在线 | av在线免费观看网站 | 欧洲一区二区三区 | 九九亚洲| 久久久www成人免费精品 | 免费av一区二区三区 | 日韩二 | 亚洲精品一区二区三区在线 | 国产精品视频久久久久 | 成人在线小视频 | 波多野结衣精品 | 久久亚洲欧美日韩精品专区 | 欧美一级精品片在线看 | 欧美一区二区三区 | 中文字幕在线一区 | 国产精品久久久亚洲 | 亚洲国产一区在线 | 亚洲欧美中文日韩在线v日本 | 久久久久久国产精品 | 91精品久久久 | 亚洲视频在线播放 | 亚洲成人免费 | 日韩免费一二三区 | 国产精品福利视频 | 亚洲看片网站 | 亚洲毛片在线 | 欧美日韩成人一区二区 | 成人a免费 | 中文字幕一区二区三区不卡 | 美女视频. | 狠狠久 | 国产高清在线精品一区二区三区 | 欧美日韩一二三区 | 日p视频免费看 | 国产在线中文字幕 | 本地毛片 | 国产成人a亚洲精品 | 日韩精品在线播放 | 国产一区二区激情视频 |