列表视图失控内存异常,但没有内存泄漏? [英] listview gets out of memory exception, but with no memory leaks?

查看:92
本文介绍了列表视图失控内存异常,但没有内存泄漏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

蜂窝后,谷歌表示,位图是由堆(讲到的此处),所以如果一个位图不再是可访问的,我们可以假设,GC照顾它并释放它。

After Honeycomb, Google said that bitmaps are managed by the heap (talked about here), so if a bitmap is no longer accessible, we can assume that GC takes care of it and frees it.

我想创建一个演示,展示显示为ListView讲座的思想的效率(从的此处),所以我做了一个小的应用程序。该应用程序可以让PSS的一个按钮,用户$ P $,然后在列表视图滚动一路底部,虽然它有10000项,其中的内容是android.R.drawable项目(姓名和图像)。

I wanted to create a demo that shows the efficiency of the ideas shown for the listView lecture (from here), so I made a small app. The app lets the user press a button, and then the listview scrolls all the way to the bottom, while it has 10000 items, which their content is the android.R.drawable items (name and image).

由于某些原因,我走出记忆,即使我不保存任何图像,所以我的问题是:这怎么可能?它是什么,我失踪?

For some reason, I get out of memory even though I don't save any of the images, so my question is: How could it be? What is it that I'm missing?

我测试的银河S III的应用程序,但我不断收到内存不足异常,如果我使用适配器的原始版本。我不明白为什么会发生,因为我不存储任何东西。

I've tested the app on a Galaxy S III, and yet I keep getting out of memory exceptions if I use the native version of the adapter. I don't understand why it occurs, since I don't store anything.

这里的code:

public class MainActivity extends Activity
  {
  private static final int LISTVIEW_ITEMS =10000;
  long                     _startTime;
  boolean                  _isMeasuring   =false;

  @Override
  public void onCreate(final Bundle savedInstanceState)
    {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    final ListView listView=(ListView)findViewById(R.id.listView);
    final Field[] fields=android.R.drawable.class.getFields();
    final LayoutInflater inflater=(LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    // listen to scroll events , so that we publish the time only when scrolled to the bottom:
    listView.setOnScrollListener(new OnScrollListener()
      {
        @Override
        public void onScrollStateChanged(final AbsListView view,final int scrollState)
          {
          if(!_isMeasuring||view.getLastVisiblePosition()!=view.getCount()-1||scrollState!=OnScrollListener.SCROLL_STATE_IDLE)
            return;
          final long stopTime=System.currentTimeMillis();
          final long scrollingTime=stopTime-_startTime;
          Toast.makeText(MainActivity.this,"time taken to scroll to bottom:"+scrollingTime,Toast.LENGTH_SHORT).show();
          _isMeasuring=false;
          }

        @Override
        public void onScroll(final AbsListView view,final int firstVisibleItem,final int visibleItemCount,final int totalItemCount)
          {}
      });
    // button click handling (start measuring) :
    findViewById(R.id.button).setOnClickListener(new OnClickListener()
      {
        @Override
        public void onClick(final View v)
          {
          if(_isMeasuring)
            return;
          final int itemsCount=listView.getAdapter().getCount();
          listView.smoothScrollToPositionFromTop(itemsCount-1,0,1000);
          _startTime=System.currentTimeMillis();
          _isMeasuring=true;
          }
      });
    // creating the adapter of the listView
    listView.setAdapter(new BaseAdapter()
      {
        @Override
        public View getView(final int position,final View convertView,final ViewGroup parent)
          {
          final Field field=fields[position%fields.length];
          // final View inflatedView=convertView!=null ? convertView : inflater.inflate(R.layout.list_item,null);
          final View inflatedView=inflater.inflate(R.layout.list_item,null);
          final ImageView imageView=(ImageView)inflatedView.findViewById(R.id.imageView);
          final TextView textView=(TextView)inflatedView.findViewById(R.id.textView);
          textView.setText(field.getName());
          try
            {
            final int imageResId=field.getInt(null);
            imageView.setImageResource(imageResId);
            }
          catch(final Exception e)
            {}
          return inflatedView;
          }

        @Override
        public long getItemId(final int position)
          {
          return 0;
          }

        @Override
        public Object getItem(final int position)
          {
          return null;
          }

        @Override
        public int getCount()
          {
          return LISTVIEW_ITEMS;
          }
      });
    }
  }


@All:我知道有优化这个code(使用convertView和viewHolder设计模式),就像我提到的谷歌作出的ListView的视频。相信我,我知道什么是更好的;这是在code整点。


@all: I know that there are optimizations for this code (using the convertView and the viewHolder design pattern) as I've mentioned the video of the listView made by Google. Believe me, I know what's better; this is the whole point of the code.

在code以上是为了显示它是更好地使用你(和视频)显示。但首先我需要表现出天真的方式;即使是用简单的方式应该仍然工作,因为我不存储位图或意见,因为谷歌已经做了同样的测试(因此他们得到了性能比较的图表)。

The code above is supposed to show that it's better to use what you (and the video) shows. But first I need to show the naive way; even the naive way should still work, since I don't store the bitmaps or the views, and since Google has done the same test (hence they got a graph of performance comparison).

推荐答案

的<一个href="http://stackoverflow.com/questions/11387269/android-out-of-memory-but-on-android-4-and-no-memory-leaks#comment15010689_11387269">comment蒂姆是当场上。您的code不使用的事实 convertView BaseAdapter.getView()方法,并保持充气新认为每一次就是为什么它最终将耗尽内存的主要原因。

The comment from Tim is spot on. The fact that your code does not utilize convertView in its BaseAdapter.getView() method and keep inflating new views every time is the major cause of why it will eventually run out of memory.

我最后一次检查,的ListView 将保留所有由 getView()方法不断返回的意见在其内部的回收站的容器,如果的ListView 从其窗口分离,将只被清除。这种回收站是如何产生的所有那些 convertView 并提供回 getView()在适当的时候。

Last time I checked, ListView will keep all the views that are ever returned by the getView() method in its internal "recycle bin" container that will only be cleared if the ListView is detached from its window. This "recycle bin" is how it can produce all those convertView and supply it back to getView() when appropriate.

作为一个测试,你甚至可以注释掉在这里你指定一个图像到您的视图中的code部分:

As a test, you can even comment out the code portion where you assign an image to your view:

                // final int imageResId = field.getInt(null);
                // imageView.setImageResource(imageResId);

和你仍然会得到内存分配失败在一个点上:)

And you will still get the memory allocation failure at one point :)

这篇关于列表视图失控内存异常,但没有内存泄漏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆