2011-09-02 104 views
2

在我的應用程序中,我從網上下載圖像。我得到了內存異常。有人建議使用下面的代碼清除堆。但是我仍然面臨着內存不足的例外情況。任何人都可以幫助我。 當活動啓動時,將調用以下方法。在這裏,我指的這個linkandroid - 內存不足

public void onStart() 
{  
    super.onStart(); 
    //Handling the out of memory exception 
    logHeap(this.getClass()); 
}  

public static void logHeap(Class clazz) { 
    Double allocated = new Double(Debug.getNativeHeapAllocatedSize())/new Double((1048576)); 
    Double available = new Double(Debug.getNativeHeapSize()/1048576.0); 
    Double free = new Double(Debug.getNativeHeapFreeSize()/1048576.0); 
    DecimalFormat df = new DecimalFormat(); 
    df.setMaximumFractionDigits(2); 
    df.setMinimumFractionDigits(2); 

    System.out.println("debug. ================================="); 
    System.out.println("debug.heap native: allocated " + df.format(allocated) + "MB of " + df.format(available) + "MB (" + df.format(free) + "MB free) in [" + clazz.getName().replaceAll("com.myapp.android.","") + "]"); 
    System.out.println("debug.memory: allocated: " + df.format(new Double(Runtime.getRuntime().totalMemory()/1048576)) + "MB of " + df.format(new Double(Runtime.getRuntime().maxMemory()/1048576))+ "MB (" + df.format(new Double(Runtime.getRuntime().freeMemory()/1048576)) +"MB free)"); 
    System.gc(); 
    System.gc();  
} 

我的代碼:

@覆蓋

public View getView(final int position, View convertView, ViewGroup parent) 

{   

     ViewHolder holder;          
     convertView = null;    

     if (convertView == null) 
     { 

      convertView = mInflater.inflate(R.layout.giftcategorieslist, null);        
      holder = new ViewHolder();          
      holder.imgitem = (ImageView)convertView.findViewById(R.id.imgitem);        
      convertView.setTag(holder); 

     } 


     else 
     { 
      holder = (ViewHolder) convertView.getTag(); 
     } 

     final CategoryData Item = arItems.get(position);   
     strItemrow = Item.toString(); 

     try 
     { 

      if(Item.dwgImage == null) 
      { 
       if(Item.bImageDownLoaded == 0) 
       {      
        holder.progress.setVisibility(View.VISIBLE);           
        DownLoadImageInAThreadHandler(Item, holder); 
       } 
       else 
       { 
        int idNoImage = R.drawable.giftsuggestionsnoimage; 
        Drawable dwgImgLoading = GiftCategories.this.getResources().getDrawable(idNoImage); 
        holder.imgitem.setImageDrawable(dwgImgLoading); 
        holder.imgitem.setVisibility(View.VISIBLE); 
        holder.progress.setVisibility(View.GONE); 
       } 
      } 
      else 
      { 
       holder.imgitem.setImageDrawable(Item.dwgImage); 
       holder.imgitem.setVisibility(View.VISIBLE); 
       holder.progress.setVisibility(View.GONE); 
      } 
    } 
    catch(Exception e) 
    { 
     System.out.println("Exception in Downloading image : " + e.getMessage()); 

    }        
     return convertView; 
    } 

    public void DownLoadImageInAThreadHandler(final CategoryData Item, final ViewHolder holder) 
     { 
      nImageDownLoads++; 

      System.out.println("The images being downloaded :" + nImageDownLoads); 



      final Handler handler = new Handler() 
      {    
       @Override public void handleMessage(Message message) 
       {     
        holder.imgitem.setImageDrawable((Drawable) message.obj); 
        holder.imgitem.setVisibility(View.VISIBLE); 
        holder.progress.setVisibility(View.GONE); 
       } 
      }; 

      //Thread for getting the attributes values 
      Thread t = new Thread() 
      { 
       public void run() 
       {      
        try 
        { 
         Item.bImageDownLoaded = 2; 
         System.out.println("Downloading image : " + Item.ImageUrl); 
         InputStream is = fetch(Item.ImageUrl); 
         Drawable drawable = Drawable.createFromStream(is, "src");             
         nImageDownLoads--; 
         System.out.println("Downloaded image :" + Item.ImageUrl); 
         System.out.println("Remaining images for downloading: " + nImageDownLoads); 
         if(drawable != null) 
         { 
          Item.dwgImage = drawable; 

          Item.bImageDownLoaded = 1; 

          //Send the message to the handler 
          Message message = handler.obtainMessage(1, drawable);     
          handler.sendMessage(message); 

         } 
         else 
         { 
          int idNoImage = R.drawable.giftsuggestionsnoimage; 
          Drawable dwgNoImg = GiftCategories.this.getResources().getDrawable(idNoImage); 

          //Send the message to the handler 
          Message message = handler.obtainMessage(1, dwgNoImg);     
          handler.sendMessage(message); 
         }      

        } 
        catch(Exception exp) 
        { 
         System.out.println("Exception in DownLoadImageInAThread : " + exp.getMessage()); 
        } 
       }            
      }; 
      t.start(); 


     } 

    private InputStream fetch(String urlString) throws MalformedURLException, IOException 
    {   
     DefaultHttpClient httpClient = new DefaultHttpClient(); 
     HttpGet request = new HttpGet(urlString); 
     HttpResponse response = httpClient.execute(request); 
     return response.getEntity().getContent(); 
    } 

    class ViewHolder 
    {   
     ImageView imgitem;      
    } 

} 

}

感謝

+3

什麼是圖像大小,你如何在活動中使用它,請顯示該代碼。 – user370305

+0

代碼添加請參考問題。 – naresh

+0

看看我編輯的答案。 – user370305

回答

8

要保存在堆中的所有圖像!

也許,如果你不向下滾動,你不會得到的內存不足的錯誤

嘗試

  • 將圖像保存到文件下載時
  • 讓你的項目對象保存圖像的路徑而不是整個Drawable

代碼

這是我創建的一個函數,它將從您的網址中獲取一個網址,並返回一個可繪製的! 它將它保存到一個文件,並獲得它,如果它存在

如果不是,它會下載它並返回drawable。

在這種情況下,您只需將url保存在Item中,並在需要drawable時將其提供給此函數。

/** 
    * Pass in an image url to get a drawable object 
    * 
    * @return a drawable object 
    */ 
    private static Drawable getDrawableFromUrl(final String url) { 
     String filename = url; 
     filename = filename.replace("/", "+"); 
     filename = filename.replace(":", "+"); 
     filename = filename.replace("~", "s"); 
     final File file = new File(Environment.getExternalStorageDirectory() 
       + File.separator + filename); 
     boolean exists = file.exists(); 
     if (!exists) { 
      try { 
       URL myFileUrl = new URL(url); 
       HttpURLConnection conn = (HttpURLConnection) myFileUrl 
         .openConnection(); 
       conn.setDoInput(true); 
       conn.connect(); 
       InputStream is = conn.getInputStream(); 
       final Bitmap result = BitmapFactory.decodeStream(is); 
       is.close(); 
       new Thread() { 
        public void run() { 
         ByteArrayOutputStream bytes = new ByteArrayOutputStream(); 
         result.compress(Bitmap.CompressFormat.JPEG, 40, bytes); 
         try { 
          if (file.createNewFile()){ 
           // 
          } 
          else{ 
           // 
          } 

          FileOutputStream fo; 
          fo = new FileOutputStream(file); 
          fo.write(bytes.toByteArray()); 
          fo.flush(); 
          fo.close(); 
         } catch (IOException e) { 
          e.printStackTrace(); 
         } 
        } 
       }.start(); 
       BitmapDrawable returnResult = new BitmapDrawable(result); 
       return returnResult; 
      } catch (FileNotFoundException e) { 
       e.printStackTrace(); 
      } catch (MalformedURLException e) { 
       e.printStackTrace(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
      return null; 
     } 
     else { 
      return new BitmapDrawable(BitmapFactory.decodeFile(file.toString())); 
     } 
    } 
+0

我的應用程序有很多圖像。存儲在文件中是否正確? – naresh

+0

這不是一個選擇。你不能將它們保存在堆中。您可以將它們保存在文件中,並將它們刪除到應用程序的「onDestroy」中,或者將它們始終保存在文件中。 –

+0

如何將它們保存在文件中? – naresh

0

在開始此過程之前,您可以嘗試運行垃圾回收(system.gc())。雖然它可能會起作用,但這不是最好的解決方案,因爲gc不會只是因爲你叫它而運行。通常情況下,如果你不得不在程序中調用gc,那就意味着你做錯了什麼。如上所示,我會嘗試將圖像移動到文件系統。