Android 如何使用ListView';香港的循环再造机制运作良好

Android 如何使用ListView';香港的循环再造机制运作良好,android,android-listview,android-gridview,Android,Android Listview,Android Gridview,所以我有这个问题,我以前有,自然我要求帮助。Luksprog的回答很好,因为我不知道ListView和GridView如何使用循环视图优化自身。因此,在他的建议下,我能够改变如何将视图添加到GridView中。问题是现在我有了一些毫无意义的东西。这是我的BaseAdapter中的getView: 问题是当我滚动时,会发生这种情况,而不是在位置0上。。。看起来像位置6和位置8,加上它把两个放在位置8。现在我仍在尝试使用ListView和GridView,所以我不明白为什么会发生这种情况。我提出

所以我有这个问题,我以前有,自然我要求帮助。Luksprog的回答很好,因为我不知道ListView和GridView如何使用循环视图优化自身。因此,在他的建议下,我能够改变如何将视图添加到GridView中。问题是现在我有了一些毫无意义的东西。这是我的
BaseAdapter
中的
getView



问题是当我滚动时,会发生这种情况,而不是在位置0上。。。看起来像位置6和位置8,加上它把两个放在位置8。现在我仍在尝试使用ListView和GridView,所以我不明白为什么会发生这种情况。我提出这个问题的主要原因之一是为了帮助其他人,他们可能不知道ListView和GridView的回收视图,或者说不知道ScrapView机制

以后编辑


添加谷歌IO对话的链接,这基本上就是了解ListView工作原理所需的全部内容。林克完全沉浸在这些评论中。所以user3427079很好地更新了这个链接。这是为了方便访问。

起初,我也不知道listview回收和convertview使用机制,但经过一整天的研究,我通过参考来自

每当适配器填充listview时,它基本上会显示listview可以在屏幕上显示的行数,即使滚动列表,行数也不会增加。这是android使用的技巧,以便listview更高效、更快速地工作。 现在listview的内部故事引用了图像,如您所见,listview最初有7个可见项,然后,如果您向上滚动直到项1不再可见,getView()将此视图(即项1)传递给回收商,您可以使用它

System.out.println("getview:"+position+" "+convertView);
在你的内心

public View getView(final int position, View convertView, ViewGroup parent)
{
    System.out.println("getview:"+position+" "+convertView);
    ViewHolder holder;
    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对于所有可见行都为null,因为最初回收器中没有视图(即项目),因此getView()会为每个可见项目创建一个新视图,但当您向上滚动,项目1移出屏幕时,它将被发送到回收器及其当前状态(例如文本视图“text”,或者在我的情况下,如果选中复选框,它将与视图关联并存储在回收器中)

现在,当您向上/向下滚动时,listview不会创建新视图,它将使用回收器中的视图。在您的日志中您会注意到“convertView”不是空的,因为您的新项目8将使用convertView绘制,即,基本上它从回收商处获取项目1视图,并在其位置对项目8进行充气,您可以在我的代码中观察到这一点。如果您有一个复选框,并且您在位置0处选中了它(假设item1有一个复选框,您选中了它),那么当您向下滚动时,您将看到已经选中了item 8复选框,这就是为什么listview会重新使用同一视图,而不是因为性能优化而为您创建新视图的原因

重要的事情

1。切勿将listview的
layout\u高度
layout\u宽度
设置为
wrap\u内容
getView()
将强制适配器获取一些子对象,用于测量列表视图中要绘制的视图的高度,并且可能会导致一些意外行为,例如返回convertview,即使列表未滚动。请始终使用
匹配父对象
或固定宽度/高度

2。如果您想在列表视图之后使用某些布局或视图,如果我将
布局高度
设置为
填充父视图
,则列表视图之后的视图将不会在屏幕下显示,因此,最好将listview放在布局中。例如,线性布局,根据需要设置该布局的高度和宽度,并将listview的高度宽度属性设置为布局的高度(如布局宽度为320高度为280)那么您的列表视图应该具有相同的高度和宽度。这将告诉getView()要渲染的视图的确切高度和宽度,getView()不会一次又一次地调用一些随机行,并且不会出现其他问题,例如在滚动之前返回convert view,我已经自己进行了测试,除非我的listview在LinearLayout中,否则它也会遇到一些问题,比如重复视图调用和将视图转换为,将listview放在LinearLayout中对我来说就像变魔术一样。(不知道为什么)


但现在问题解决了,我知道,我不太擅长解释,但我花了一整天的时间去理解,所以我想其他像我这样的初学者可以从我的经验中得到帮助,我希望大家现在能稍微了解一下ListView框架的工作原理,因为它非常混乱和棘手,所以初学者在理解它时发现太多问题

注意,在Holder模式中,如果您在Holder对象中设置了位置,则每次都应该设置它,例如:

@Override
public final View getView(int position, View view, ViewGroup parent) {
    Holder holder = null;
    if (view == null) {
        LayoutInflater inflater = (LayoutInflater) App.getContext()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        view = inflater.inflate(getContainerView(), parent, false);
        holder = getHolder(position, view, parent);
        holder.setTag(tag);
        view.setTag(holder);
    } else {
        holder = (Holder) view.getTag();
    }
    holder.position = position;
    draw(holder);
    return holder.getView();
}
这是一个抽象类的示例,其中

getHolder(position, view, parent);
执行所有的设置操作

ImageViews, TextViews, etc..

使用支架模式,您可以实现您想要的:


当您向下滚动屏幕并隐藏上面的列表视图项目时,列表视图将循环使用。它们被重新使用以显示新的列表视图项。

哈哈,谢谢你的链接。现在开始看:)您没有完全实现上一个问题中的代码示例。这个想法是,您总是需要一段代码来恢复对其他行所做的更改(在您的情况下是位置
0
)。我理解@Luksprog,但这是否解释了为什么它也将视图放在其他位置?如果有的话,我只期望位置0
getHolder(position, view, parent);
ImageViews, TextViews, etc..