【问题标题】:android - out of memory安卓——内存不足
【发布时间】:2011-09-02 10:43:44
【问题描述】:

在我的应用程序中,我正在从网络下载图像。我得到了内存异常。有人建议使用以下代码清除堆。但是我仍然面临内存不足的异常。有人可以帮助我吗? 活动启动时调用以下方法。这里我指的是这个link

  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();       
}

我的代码:

@Override

 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;                      
    }

 }

}

谢谢

【问题讨论】:

  • 图片大小是多少,您是如何在活动中使用它的,请出示该代码。
  • 代码已添加,请参考问题。

标签: android out-of-memory


【解决方案1】:

您正在保存堆中的所有图像!

如果不向下滚动,可能不会出现内存不足错误

尝试

  • 下载后保存图片
  • 让您的 Item 对象保存图像的路径,而不是整个 Drawable

代码

这是我创建的一个函数,它会从你那里获取一个 url,它会返回一个 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()));
        }
    }

【讨论】:

  • 这不是一个选择。您不能将它们保存在堆中。您可以将它们保存在文件中并删除它们onDestroy 的应用程序,或者将它们始终保存在文件中。
  • 在您的Thread t = new Thread() 中使用 getDrawableFromUrl(final String url) 获取图像并以相同的方式工作
  • 另一件事如何说图像存储在我的代码中的堆内存中。
  • 因为每个CategoryData 都有位图!...让它只有一个字符串(url)(:
  • 那么图片存放在哪里?
【解决方案2】:

您可以在开始此过程之前尝试运行垃圾收集(system.gc())。虽然它可能有效,但这不是最好的解决方案,因为 gc 不会因为你调用它而总是运行。通常如果你必须在你的程序中调用 gc 这意味着你做错了什么。我会尝试按照上面的建议将图像移动到文件系统。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-06
    • 1970-01-01
    • 2013-08-24
    • 1970-01-01
    • 2018-09-29
    • 2012-06-29
    相关资源
    最近更新 更多