如何ListView的回收机制的工作原理 [英] How ListView's recycling mechanism works

查看:153
本文介绍了如何ListView的回收机制的工作原理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我有这个问题,我收到了,自然我要求在<帮助href="http://stackoverflow.com/questions/11919033/why-do-i-need-to-call-removeview-in-order-to-add-a-view-to-my-linearlayout/11920159#11920159">here. Luksprog的回答是伟大的,因为我不知道如何ListView控件和GridView优化本身回收利用意见。所以他建议我可以改变我如何添加浏览到我的GridView控件。问题是,现在我有一些没有意义。这是我的 getView 从我的 BaseAdapter

So I have this problem I had before, and naturally I asked for help on here. Luksprog's answer was great because I had no idea about how ListView and GridView optimized itself with recycling Views. So with his advice I was able to change how I added Views to my GridView. Problem is now I have something that does not make sense. This is my getView from my BaseAdapter:

public View getView(int position, View convertView, ViewGroup parent) {
        if(convertView == null) {
            LayoutInflater inflater = LayoutInflater.from(parent.getContext());
            convertView = inflater.inflate(R.layout.day_view_item, parent, false);
        }
        Log.d("DayViewActivity", "Position is: "+position);
        ((TextView)convertView.findViewById(R.id.day_hour_side)).setText(array[position]);
        LinearLayout layout = (LinearLayout)convertView.findViewById(R.id.day_event_layout);

        //layout.addView(new EventFrame(parent.getContext()));

        TextView create = new TextView(DayViewActivity.this);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 62, getResources().getDisplayMetrics()), 1.0f);
        params.topMargin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics());
        params.bottomMargin = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, getResources().getDisplayMetrics());
        create.setLayoutParams(params);
        create.setBackgroundColor(Color.BLUE);
        create.setText("Test"); 
        //the following is my original LinearLayout.LayoutParams for correctly setting the TextView Height
        //new LinearLayout.LayoutParams(0, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 60, getResources().getDisplayMetrics()), 1.0f)   
        if(position == 0) {
            Log.d("DayViewActivity", "This should only be running when position is 0. The position is: "+position);
            layout.addView(create);
        }

        return convertView;
    }

}


问题是,当我滚动,出现这种情况,而不是位0 ...貌似位置6和第8位,再加上它把两个位置8.现在我仍然在试图让使用ListView和GridView控件的窍门所以我不明白为什么会这样。其中一个我提出这个问题的主要原因是为了帮助别人谁可能不知道ListView和GridView的循环观,还是这个方法的文章所说的那样,ScrapView机制。


Problem is when I scroll, this happens, and not on position 0... Looks like position 6 and position 8, plus it puts two in position 8. Now I am still trying to get the hang of using ListView and GridView so I do not understand why this is happening. One of the main reasons I am making this question is to help others who probably don't know about ListView and GridView's recycling View, or the way this article puts it, ScrapView mechanism.

后来修改

添加链接到谷歌的IO说话,基本上是所有你需要了解的ListView工作。链接是死在了意见。所以user3427079是不够好,以更新的链接。 这里的是为了方便客人。

Adding link to a google IO talk that is basically all you need to understand how ListView works. Link was dead in on of the comments. So user3427079 was nice enough to update that link. Here it is for easy access.

推荐答案

起初,我还没有意识到的ListView回收及convertview使用机制,但过了整整两天的研究,我pretty的多少了解列表视图的机制从 android.amberfog 指图像

Initially I was also unaware of listview recycling and the convertview usage mechanism, but after a whole days research I pretty much understand the mechanisms of the list view by referring to an image from android.amberfog

当过您的ListView充满适配器,它基本上显示了的列表视图可以在屏幕上显示的数量和行数犯规您滚动列表得到提高,甚至,这是招的Andr​​oid应用,使ListView的工作更加,有效的,快速的, 现在列表视图。参见图像的内情,你可以看到初始列表视图中有7个明显的项目,如果你向上滚动时,第1项是没有任何更多可见的getView()通过这种观点(ITEM1),以回收,您可以使用

When ever your listview is filled with an adapter it basically shows the number of Rows that the listview can show on screen and the number of rows doesnt get increase even you scroll through the list, this is the trick android use so that listview work more effcient and fast, Now the inside story of listview refering to image as you can see initially list view has 7 visible items, if you scroll up when item 1 is not any more visible getView() pass this view(item1) to recycler and you can use

System.out.println("getview:"+position+" "+convertView);

在你的

public View getView(final int position, View convertView, ViewGroup parent)
{
    System.out.println("getview:"+position+" "+convertView);
    View row=convertView;
    if(row==null)
    {
        LayoutInflater inflater=((Activity)context).getLayoutInflater();
        row=inflater.inflate(layoutResourceId, parent,false);

        holder=new PakistaniDrama();
        holder.tvDramaName=(TextView)row.findViewById(R.id.dramaName);
        holder.cbCheck=(CheckBox)row.findViewById(R.id.checkBox);

        row.setTag(holder);

    }
    else
    {
        holder=(PakistaniDrama)row.getTag();
    }
            holder.tvDramaName.setText(dramaList.get(position).getDramaName());
    holder.cbCheck.setChecked(checks.get(position));
            return row;
    }

你会发现在你的logcat最初convertview是所有可见的行空的,因为最初有在回收没有视图(项目),让你的getView()创建为可见的项目每一个新的观点,但一时滚动你的第1项将发送到回收站与它的状态(例如TextView的文本,并在我的情况下,如果复选框被选中它也将与回收的视图和存储相关的)。 现在,当你向上/向下滚动的列表视图不会创建一个新视图将使用视图(转换视图)这已经是你的回收站,在您的的logcat 您会发现,convertView不空,它是因为新的项目8将使用convertview,即可以得出,基本上采取的回收和充气的ITEM1视图代替第8项的,你可以看到,在我的code,如果你有一个复选框如果你在位置0检查(让说ITEM1也有一个复选框,你检查的话),所以当你向下滚动,你会看到第8项的复选框已被选中,这就是为什么列表视图是重新使用不是创建一个新的相同的看法你因性能优化。

you will notice in your logcat initially convertview is null for all the visible rows, because initially there were no view(item) in recycler, so your getView() creates each new view for the visible items, but the moment you scroll up your item 1 will send to the Recycler with it state(for example the TextView text and as in mine case if checkbox is checked it will also be associated with the view and store in recycler). Now when you scroll up/down your listview is not going to create a new view it will use the view(convert view) which is already in your recycler, in your Logcat you will notice that convertView is not null, its because your new item 8 will be drawn using convertview, i.e., basically it take the item1 view from the recycler and inflater in place of item 8, and you can observe that as in mine code if you had a checkbox and if you check it at position 0(let say item1 has also a checkbox and you checked it) so when you scroll down you will see item 8 checkbox is already checked, this is why listview is re using the same view not creating a new for you due to performance optimization.

重要的事情

1 。决不将 layout_height layout_width 您的列表视图,以 WRAP_CONTENT 的为 getView()将迫使适配器得到一些孩子测量的意见高度在列表视图中被绘制,并可能导致好像回到convertview甚至列表中的一些异常行为不scrolled.always使用 match_parent 或固定宽度/高度。

1. Never set the layout_height and layout_width of your listview to wrap_content as getView() will force your adapter to get some child for measuring the height of the views to be drawn in list view and can cause some unexpected behaviour like returning convertview even the list is not scrolled.always use match_parent or fixed width/height.

2 。如果你想使用一些布局或查看您的列表视图和问题后,可能会在你的头脑来,如果我设置 layout_height FILL_PARENT 后,列表视图,视图将不会出现,因为它出现故障的屏幕,所以它能够更好地把你的ListView里面layout.For例如线性布局,并设置布局的高度和宽度,作为您的要求,使宽度您的列表视图中为布局的属性(比如,如果你的布局宽度 320 并高度 280),然后你的ListView应该有相同的宽度。这将告诉精确的高度和宽度的意见getView()来渲染,和getView()不会再次打电话又有些乱行,其他的问题,如之前滚动不会发生转换回来看,我有测试这个我自己,除非我的列表视图是lineaLayout它也有类似观点的重复呼叫,并转换成视图,将列表视图里面的LinearLayout,像变魔术一样,我的问题里面。(不知道为什么)

2. If you want to use some Layout or view after your list view and question might came in your mind if i set the layout_height to fill_parent the view after list view will not show up as it goes down the screen, so its better to put your listview inside a layout.For example Linear Layout and set the height and width of that layout as of your requirement and make the height and width attribute of your listview to as of your layout(like if your layout width is 320 and height is 280) then your listview should have same height and width. This will tell getView() of exact height and width of views to be rendered, and getView() won't call again and again some random rows, and other problems like returning convert view even before scrolling won't happen, i have test this myself, unless my listview was inside the lineaLayout it was also having problems like repeating view call and convert view as, putting Listview inside LinearLayout worked like magic for me.(didn't know why)

01-01 14:49:36.606: I/System.out(13871): getview 0 null
01-01 14:49:36.636: I/System.out(13871): getview 0 android.widget.RelativeLayout@406082c0
01-01 14:49:36.636: I/System.out(13871): getview 1 android.widget.RelativeLayout@406082c0
01-01 14:49:36.646: I/System.out(13871): getview 2 android.widget.RelativeLayout@406082c0
01-01 14:49:36.646: I/System.out(13871): getview 3 android.widget.RelativeLayout@406082c0
01-01 14:49:36.656: I/System.out(13871): getview 4 android.widget.RelativeLayout@406082c0
01-01 14:49:36.666: I/System.out(13871): getview 5 android.widget.RelativeLayout@406082c0
01-01 14:49:36.666: I/System.out(13871): getview 0 android.widget.RelativeLayout@406082c0
01-01 14:49:36.696: I/System.out(13871): getview 0 android.widget.RelativeLayout@406082c0
01-01 14:49:36.706: I/System.out(13871): getview 1 null
01-01 14:49:36.736: I/System.out(13871): getview 2 null
01-01 14:49:36.756: I/System.out(13871): getview 3 null
01-01 14:49:36.776: I/System.out(13871): getview 4 null

但现在它解决了,我知道,我不是在解释好,但我把我整天理解,所以我想其他的初学者和我一样能得到我的经验帮助,我希望现在你的人都会有一个对的ListView 框架,它是如何工作的,因为它是非常的混乱和麻烦所以初学者发现太多问题理解它有点理解

But now its solved, I know, I'm not that good at explaining but as i put my whole day to understand so i thought other beginners like me can get help of my experience and i hope now you people will have a little bit understanding of ListView framework how it works, as it is really messy and tricky so beginners found too much problem understanding it

这篇关于如何ListView的回收机制的工作原理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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