Android Listview';s getView()不是';t使用两种不同的列表项时工作正常

Android Listview';s getView()不是';t使用两种不同的列表项时工作正常,android,android-listview,android-arrayadapter,custom-arrayadapter,Android,Android Listview,Android Arrayadapter,Custom Arrayadapter,我有一个用于Listview的自定义数组适配器,我将它用于联系人,因为我希望Listview更加有序,我希望为联系人姓名的第一个字母添加一个标题 这是我目前的进展: @NonNull @Override public View getView(final int position, @Nullable View convertView, @NonNull ViewGroup parent) { View listItem = convertView;

我有一个用于Listview的自定义数组适配器,我将它用于联系人,因为我希望Listview更加有序,我希望为联系人姓名的第一个字母添加一个标题 这是我目前的进展:

@NonNull
    @Override
    public View getView(final int position, @Nullable View convertView, @NonNull ViewGroup parent) {
        View listItem = convertView;
        LinearLayout header = null;
        String preLabel = " ";
        char firstChar = ' ';
        final Contact c = Contacts.get(position);
        String label = c.name;
        if(position != 0) {//OOb prevention
            preLabel = Contacts.get(position - 1).name;
            firstChar = label.toUpperCase().charAt(0);
        }



        char preFirstChar = preLabel.toUpperCase().charAt(0);
        if (listItem == null) {
            //If its the 1st position or the 1st character of the name is different inflate the layout with a header, else inflate the other layout.
            if(position==0 || firstChar != preFirstChar) {

                listItem = LayoutInflater.from(mContext).inflate(R.layout.contacts_list_item, parent, false);
                header  = (LinearLayout) listItem.findViewById(R.id.section);
                setSection(header, label);
            }else{
                listItem = LayoutInflater.from(mContext).inflate(R.layout.contacts_list2, parent, false);
            }
        }//Etc etc
我认为添加更多的代码是不相关的,即使在我确定何时放置标题的逻辑错误的情况下,这也是一种奇怪的行为,因为当我向下滚动到视图不可见或在我向后滚动时视图不被破坏的点时,位置0没有标题

如果我继续做同样的事情,突然它自己修复了,现在第一个位置又有了一个标题,再滚动一次,现在没有了,为什么会发生这种情况? 适配器是否使用其他方法创建视图? 它是否试图预测它将使用哪种布局来加快速度

错误的视觉参考:


正如您所看到的,位置0(为了简单起见,我将位置号放在textview中,而不是联系人的姓名)在开始处有一个标题,滚动一点后,它就会消失,然后重新出现。

当您滚动视图时,视图会离开可见区域,ListView将对列表中的其他位置重复使用相同的膨胀视图

因此,如果您的
getView
方法中的逻辑有时会膨胀
R.layout.a
,有时会膨胀
R.layout.b
,从而导致麻烦,因为这样您可能会得到一个需要重复使用的
convertView
,它的类型是
a
,但对于列表中的这个特定位置,您需要一个
b
类型的视图

解决方案是使用
ViewType
s,这是告诉ListView您有两种不同类型的布局的方式,然后它知道何时可以回收某个类型,以及使用哪个
View

基本上,您应该返回override
getViewTypeCount()
并返回2(您有两种类型的布局),并将检查是否需要标题的逻辑移动到
getItemViewType(int位置)


请参见此处:

RecyclerView在视图不可见时丢弃视图,并在视图再次可见时重新创建视图,因此它类似于基于滚动的动态加载。我认为你选择视图类型的方式可能没有得到优化,如果你做得更好,它可以更快地加载你的视图listview使用recyclerview吗?对不起,我误读了你的评论,做一个通用listview并不比添加联系人更好,在你将它加载到适配器之前,你添加了表示你的标题的字符串,然后在getView中,您只需检查该位置是字符串类型还是触点类型,即可为相应的视图充气。Idk,我仍然认为你这样做并不仅仅是为了增加一个不同的布局。但即使这根本不是最优的,我也可以改变它,但我的问题仍然是,为什么会发生这种情况?是虫子吗?有什么我不知道的原因吗?