記一次Android下載進程的內存優化


        關於大多數程序猿(碼農)來講,一提到內存優化一定都是比較頭大,我也不破例,但是由於我們這個項目就我一我的作,出疑問了也沒有大牛處理,因此只能是自個硬着頭皮上了。 服務器

       言歸正傳,先告知一下工做的原因。樓主是作網盤項目的,從從未觸摸過度塊上載、斷點續傳(曾經一聽斷點續傳也是頭大)到牽強把分塊上載下載作完,也是閱歷了不少苦楚的,但是,有一個工做一貫是我不肯供認不想面臨但卻恰恰存在的疑問,那便是下載的時分界面十分卡頓!是十分卡,不是通常的卡!小文件還好,感受不出來,但是一超越100M就會十分卡甚至是ANR。沒辦法了,儘管我一貫想躲避,但是這個總需求處理,只能硬着頭皮來了! 優化

    

     首要我是這麼作的,通過httpClient獲得HttpEntity,在複製一份Entity,而後通過EntityUtils.toString取得數據內容(信任大多數運用HttpClient的都是這麼作),而後從內容裏截取出文件頭,運用複製的entity取得輸入流,越過文件頭長度再寫文件,大體代碼以下: 網站


Java代碼   保藏代碼
  1. HttpEntity responseEntity = kscResponse.getResponse().getEntity();  
  2. HttpEntity responseEntityClone = responseEntity;//爲什麼複製一份?  
  3. InputStream in = responseEntityClone.getContent();  
  4. String data = EntityUtils.toString(responseEntity);  
  5. String customHeader = data.substring(0,data.indexOf("\n")+1);  
  6.  in.skip(customHeader.length());  
  7. //下面從流裏寫文件  
  8. ...  

 這裏有一個會導致OOM的疑問,便是EntityUtils.toString(responseEntity); 辦法,我發如今上載叫大文件的時分會潰散,我想是這個辦法會把一切內容讀取出來放到內存裏,假如文件較大的話天然會潰散,因此這個當地改爲了自個寫的InputStream2String辦法,具體代碼不寫了,很經常使用,僅有的關鍵是當讀取到一個size的時分(服務器約束的協議頭最大長度)就跳出循環不在讀取後邊的數據,這麼內存中最大也便是幾k的數據,不會導致OOM了;但是,以前的卡頓狀況還是每樣處理。 spa

  而後開始各類查資料,各類「優化」之後(好比不要在循環裏new 目標等),做用仍然不抱負。打開DDMS東西檢查Allocation Tracker檢查內存分配狀況,發現還是下載的那個當地內存較大,原本我也知道HttpEntity responseEntityClone = responseEntity;複製這個當地可能會佔用內存,但是也沒辦法啊,我需求先讀取輸入流把文件頭取出來而後再寫文件,但是讀取輸入流的時分就把responseEntity耗費掉了,後邊也寫不了文件了。後來俄然想到BufferedReader 有一個readline辦法,便是每次讀取一行,已\r或者\n作標識,大喜之下嘗試了一下,結果很使人失望,下載下來的文件和有損壞。。。失望之下檢查了下readline的源碼,深受啓發!修改了一下InputStream2String的代碼,搞定!InputStream2String代碼以下: blog

  

Java代碼   保藏代碼
  1. public static String InputStream2String(InputStream is)  
  2.             throws KuaipanException {  
  3.         if (is == null) {  
  4.             return null;  
  5.         }  
  6.   
  7.         ByteArrayOutputStream baos = new ByteArrayOutputStream();  
  8.         byte[] buf = new byte[BUFFER_SIZE];  
  9.         int len = 0;  
  10.         int total = 0;  
  11.         try {  
  12.             while ((len = is.read(buf,0,1)) != -1) {  
  13.                 byte ch = (byte)buf[0];  
  14.                 if (ch == '\n') {  
  15.                     break;  
  16.                 }  
  17.                 baos.write(buf, 0, len);  
  18. //                total+=len;  
  19.                 total++;  
  20. //                if(total >=MAX_COUNT)  
  21. //                    break;  
  22.             }  
  23.         } catch (IOException e) {  
  24.             throw new KuaipanException(KuaipanException.IO_ERROR_CODE,  
  25.                     "stream2String IOException", e);  
  26.         }  
  27.   
  28.         String result = null;  
  29.   
  30.         byte[] byteArray = baos.toByteArray();  
  31.         int size = MAX_COUNT>byteArray.length?byteArray.length:MAX_COUNT;  
  32.         result = new String(byteArray,0,size);  
  33.   
  34.         return result;  
  35.     }  

   先是一個個字符去讀取,當讀取到\n的時分,就再也不讀了,這麼回來的數據恰好是文件頭,後邊自個也不需求自個去截取data.substring(0,data.indexOf("\n")+1);文件頭了,相同,這個inputsream沒有耗費完,下面可以接着寫文件了,也沒必要in.skip(customHeader.length());了 具體網站:http://www.keymob.com/ ip

相關文章
相關標籤/搜索