gpt4 book ai didi

android - listview 出现内存不足异常,但没有内存泄漏?

转载 作者:太空宇宙 更新时间:2023-11-03 12:00:10 26 4
gpt4 key购买 nike

在 Honeycomb 之后,Google 表示位图由堆管理(讨论了 here ),因此如果位图不再可访问,我们可以假设 GC 会处理并释放它。

我想创建一个演示来展示 listView 讲座(来自 here)所展示的想法的效率,所以我制作了一个小应用程序。该应用程序让用户按下一个按钮,然后 ListView 一直滚动到底部,同时它有 10000 个项目,它们的内容是 android.R.drawable 项目(名称和图像)。

出于某种原因,即使我没有保存任何图像,我的内存也不足,所以我的问题是:怎么会这样?我缺少什么?

我已经在 Galaxy S III 上测试了该应用程序,但如果我使用 native 版本的适配器,我会不断遇到内存不足异常。我不明白为什么会这样,因为我没有存储任何东西。

代码如下:

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:我知道这段代码有优化(使用 convertView 和 viewHolder 设计模式),因为我已经提到了 Google 制作的 listView 的视频。相信我,我知道什么更好;这就是代码的全部要点。

上面的代码应该表明最好使用您(和视频)显示的内容。但首先我需要展示天真的方式;即使是最简单的方法也应该仍然有效,因为我不存储位图或 View ,而且 Google 已经进行了相同的测试(因此他们得到了性能比较图)。

最佳答案

comment from Tim是正确的。您的代码没有在其 BaseAdapter.getView() 方法中使用 convertView 并且每次都不断增加新 View 的事实是它最终会耗尽的主要原因内存。

我上次检查时,ListView 会将 getView() 方法返回的所有 View 保存在其内部“回收站”容器中,该容器只会被如果 ListView 与其窗口分离,则清除。这个“回收站”是它如何生成所有这些 convertView 并在适当的时候将其提供回 getView()

作为测试,您甚至可以注释掉将图像分配给 View 的代码部分:

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

而且你仍然会在某一时刻遇到内存分配失败:)

关于android - listview 出现内存不足异常,但没有内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11387269/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com