1

I have a ListView in my app that is used to show a list with 2 types of items. The way it is currently implemented is that I have two different XML layouts for each of the item types, my adapter correctly reports the type and in the getView() method I inflate the appropriate XML according the the type in the specified position.

The problem is that in the vast majority of cases the structure of the list of items is that most of the type 1 items are in the beginning and most of the type 2 items are in the end, so usually at first you see mostly type 1 items, you scroll down and at some point you start seeing type 2 items, and they continue until the end of the list.

All works fine while I scroll until I hit that midpoint. Around that point all the calls to getView() get null passed as the convertView parameter. This makes sense obviously. The problem is that is seems like ListView stores all the previous type 1 views in the recycler, and I will not use them as long as I keep scrolling down since from now on most of the views will be type 2 views.

The views are pretty complex, with custom background and bitmaps on top of it, so I end up with lots of views in memory that I will probably never use.

My question is twofold:

  1. Should I even worry about it? right now I am not in the point where I get OOM exceptions, but will I ever get there or is ListView smart enough to "let go" of some of those views when resources get tight?

  2. If I do need to worry about it, is there a way to explicitly tell ListView to clear up it's recycler, or even disable it somehow?

A possible solution is to use the same XML for both layouts, have two ViewGroups in there and just set the visibility of one of them to GONE, but it seems like a waste to have a fairly complex view hierarchy if I am never going to show it.

4

3 回答 3

1

我应该担心吗?

不,因为用户完全能够向上滚动,从而返回到类型 1 行。

现在我还没有遇到 OOM 异常,但是我会到达那里吗?或者 ListView 是否足够聪明,可以在资源紧张时“放开”其中一些视图?

一旦您开始收到OutOfMemoryError消息,这ListView将不是您的问题。您只有这么多行View结构,从内存消耗的角度来看,所有这些都应该非常便宜。

于 2013-09-16T23:48:26.443 回答
1

在适配器中处理两种不同类型的子视图的一个建议是使用getViewTypeCount方法并让适配器知道您实际上使用了两种不同类型的视图。

listView 为每种视图类型维护每个回收器(在您的情况下,数字将为 2),因此您不必担心任何 OOM 异常,也不需要告诉 ListView 清理它的回收器。

有关更详细的说明,请查看:ArrayAdapter 的 getViewTypeCount 和 getItemViewType 方法

实现代码片段:

public class SampleAdapter extends ArrayAdapter<String> {

    ...

    @Override
    public int getViewTypeCount() {
        return 2;
    }

    @Override
    public int getItemViewType(int position) {
        //the result must be in the range 0 to getViewTypeCount() - 1.
        if( position < 10 )
            return 0;
        else
            return 1;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        switch( getItemViewType(position) ){
            case 0:
                //do something for type1 view.
                break;
            case 1:
                //do something for type2 view.
                break;
        }
        return convertView;
    }
}
于 2013-09-16T23:39:56.523 回答
0

当只有 2 种视图类型时,我不会太担心。

如果要优化它,我建议不要使用非常复杂的布局,而是使用自定义View并自己绘制Bitmaps。一个更复杂的任务,但在通过中点时会带来更好的用户体验。

于 2013-09-16T23:52:18.890 回答