安卓自定义列表视图

4

我看了教程,也做了搜索,但是仍然无法理解如何实现,

getView(int position, View convertView, ViewGroup arg2)

当我使用BaseAdapter进行扩展以创建自定义listView时,此方法可用。因此,我无法完全按照自己的意愿编辑自定义列表。

我需要了解此方法何时调用以及参数的含义。

如果有人能够解释以下方法,那就太好了。谢谢。

@Override
public View getView(int position, View convertView, ViewGroup arg2)
{

    ViewHolder holder;
    LayoutInflater inflater =  context.getLayoutInflater();

    if (convertView == null)
    {
        convertView = inflater.inflate(R.layout.listitem_row, null);                     
        holder = new ViewHolder();
        holder.txtViewTitle = (TextView) convertView.findViewById(R.id.textView1);
        holder.txtViewDescription = (TextView) convertView.findViewById(R.id.textView2);

        convertView.setTag(holder);
    }
    else
    {
        holder = (ViewHolder) convertView.getTag();                                        
    }

    holder.txtViewTitle.setText(title[position]);
    holder.txtViewDescription.setText(description[position]);



  return convertView;
}
3个回答

4

getView()在调用setAdapter后被调用。之后,当你在列表上移动焦点或选择任何项或调用notifyDataSetChanged()时,你将在getView()中得到调用。

Position - 我们想要其视图的项在适配器数据集内的位置。

convertView - 以前要重用的视图(如果可能)。注意:在使用之前,应检查此视图是否非空且类型合适。如果无法将此视图转换为显示正确数据,则此方法可以创建新视图。异构列表可以指定其视图类型的数量,以便此视图始终是正确类型的

最终将附加此视图的ViewGroup


嗨,vineetska,感谢您的回答。在我的代码中,当我想要加载这个列表时,getView()方法会调用List view中记录数量的三倍。我通过创建一个日志来检查它。不明白为什么会这样。 - JibW
在getView()方法中的if块内,使用"LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);"代替"LayoutInflater inflater = context.getLayoutInflater();"。 - Vineet Shukla
仍然是同样的方式。用这种方法有点混乱...真的无法弄清楚执行过程...执行此方法的次数是记录数量的三倍(当列表中显示2个listview记录时,此方法运行6次)。 - JibW

3

getView() :如规范中所述,getView方法显示指定位置的数据。因此,当您设置Adapter并滚动listView时,将调用getView方法。

您复制的方法是EfficientAdapter的一部分,旨在优化ListView性能,并使用ViewHolder模式进行优化。

从规范中复制:稍作解释

position:我们想要查看其视图的项目在适配器数据集内的位置。

convertView:如果可能,可以重用旧视图。注意:在使用之前,应检查此视图是否非空且类型适当。如果无法将此视图转换为显示正确数据,则此方法可以创建新视图。异构列表可以指定其视图类型数量,以便该视图始终是正确类型(请参见getViewTypeCount()和getItemViewType(int))。

因此,在上述方法中,当您执行以下操作时,您正在重用convertView。

     if (convertView == null){
            ....
            convertView.setTag(holder);
     } else {
           holder = (ViewHolder) convertView.getTag(); 
      }

通过使用以下方法,您可以避免查找(findViewById),这就是ViewHolder模式的好处。
      holder.txtViewTitle = (TextView) convertView.findViewById(R.id.textView1);

parent : 这个视图最终将附加到的父视图

编辑

问题:getView方法会被调用多少次,会创建多少个convertView? 答案:以ApiDemos中的Efficeint Adapter示例为例。如果您的屏幕显示10行,则:

convertView计数:10 + 1 = 11(您在屏幕上看到的10行,额外的一行用于显示滚动效果)。这意味着if(convertView == null){...}块中的语句仅会被调用11次。

getView计数:初始计数为10,但当您开始滚动时,计数会不断增加。每次调用getView来更新数据。

注意:这仅适用于问题中提到的getView方法。


是的,但是当我使用这种方法将项目加载到listview中时,getView()方法运行的次数是要显示的元素数量的三倍。我不明白为什么...... - JibW
嗨gopal,非常感谢。但是我尝试将4个元素加载到listview中进行测试。所以getview()方法执行了12次。每次运行都比在listview中显示的元素数量多3次... 有点困惑...! - JibW
@JibW 尝试将计数器放在 if (convertView == null) { //your count statement } 内。数字应该会减少。正如我在答案中提到的,getView 方法在设置适配器和滚动时被调用。尝试这个方法,如果你仍然得到奇怪的数字,请告诉我... - Gopal
当我把计数器放在 (convertView == null) { } 内时,它会在加载 4 个元素到 ListView 时运行 5 次。 - JibW
抱歉,在我之前的评论中忘记提到,它将创建一个额外的视图,以展示滚动效果。 - Gopal
显示剩余2条评论

2
以下是getView()参数的描述: int position - 视图在列表中的位置; View convertView - 在列表开始工作时,convertView = null。但是当你开始向下滚动它时,列表项(它是View的实例)被隐藏时,它会像convertView一样存储在内存中。这个技巧允许你在滚动列表时不必创建新的项目,而是使用在内存中存储的convertView。所以第一个成为convertView的列表项是0位置的项。请记住,当你向下滚动你的ListView(从0位置到更大),convertView位于顶部,在向上滚动ListView时位于底部。 ViewGroup arg2 - 这是你的ListView(这个类派生自ViewGroup)。 ViewHolder是一种模式,使与列表项的舒适交流。你将这个对象作为项目的标记,并可以将它们用于间接地与列表项交互,因为它引用了项的字段(View.setTag(holder))。
每次Android需要绘制另一个列表项时都会调用getView()方法。
还有问题吗?

谢谢teoREtik...使用这种方法将项目加载到listview中时,getView()方法运行的次数是要显示的元素数量的三倍(例如,如果要加载2个元素到listview中,则getView()方法运行6次)。我不明白为什么会这样......而且在创建convertView = inflater.inflate(R.layout.listitem_row, null)之后,通过检查convertview==null,在加载元素到listview时它会运行多次。 - JibW

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接