记一次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

相关文章
相关标签/搜索