记一次Android下载进程的内存优化




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了;可是,之前的卡顿情况仍是每样处理。

  然后开始各种查资料,各种“优化”以后(比如不要在循环里new 目标等),作用仍然不抱负。打开DDMS东西检查Allocation Tracker检查内存分配情况,发现仍是下载的那个当地内存较大,本来我也知道HttpEntity responseEntityClone = responseEntity;复制这个当地可能会占用内存,可是也没办法啊,我需求先读取输入流把文件头取出来然后再写文件,可是读取输入流的时分就把responseEntity耗费掉了,后边也写不了文件了。后来俄然想到BufferedReader 有一个readline办法,即是每次读取一行,已\r或者\n做标识,大喜之下尝试了一下,结果很令人失望,下载下来的文件和有损坏。。。失望之下检查了下readline的源码,深受启发!修改了一下InputStream2String的代码,搞定!InputStream2String代码如下:

  

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/



你可能感兴趣的:(记一次Android下载进程的内存优化)