Android ListView适配器崩溃问题/重复数据

3
我基本上是想通过同一个ListView适配器来显示多个视图。然而,适配器最终会生成多个重复项,并有时会崩溃并出现空指针异常。我猜想我的适配器实现方式有误。以下是完整的代码:

该项可能是照片文字

适配器:

 public class FeedAdapter extends BaseAdapter {

        static private Activity activity;
        private static LayoutInflater inflater = null;
        ArrayList<ActivityTable> actList = new ArrayList<ActivityTable>();
        Holder holder;

    public FeedAdapter(Activity a, ArrayList<ActivityTable> actList) {
            activity = a;
            this.actList = actList;
        }

    public View getView(int position, View convertView, ViewGroup parent) {

            Holder holder;

            final ActivityTable act = actList.get(position);
    inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

     if (convertView == null) {

                if (act.getType().equals("text")) {

                    convertView = inflater.inflate(R.layout.feed_single_text, null);
                    holder = new Holder();

                    //More code that Set the caption to the holder
                    convertView.setTag(holder);

                }

                if (act.getType().equals("photo")) {

                    convertView = inflater.inflate(R.layout.feed_single_picture, parent, false);
                    holder = new Holder();
                    holder.media = (ImageView) convertView.findViewById(R.id.postphoto);
                    //More code that Set the photo to the holder
                    convertView.setTag(holder);
                }

            } else {

                holder = (Holder) convertView.getTag();

            }

         return convertView;
    }


    public static class Holder {
           ImageView media;
           TextView caption;
    }
}

我用同一个适配器填充多个视图,这样做是错误的吗?有没有人能指出问题所在?

你能发布一下设置每行数据的代码吗?我的意思是在"return convertView"上面和else{...}下面的代码。 - Linh
为什么你还在使用ListView,而不选择更好的替代方案呢?难道是因为你正在维护遗留代码吗? - Avinash R
@AvinashR 有更好的替代方案吗? - Jay
@PhanVănLinh 即使没有设置数据,我也会得到重复行。 - Jay
@Earthling 显然是 RecyclerView - Avinash R
1
请发布错误堆栈。不知道错误是什么,这些人怎么发布答案呢? - Viswanath Lekshmanan
4个回答

1
你的每一行有两种不同的布局,因此我认为你应该添加。
@Override
public int getViewTypeCount() {
    return 2;
}

添加到您的列表视图适配器中
在您的代码中,尝试在适配器的构造函数中初始化您的LayoutInflater

public FeedAdapter(Activity a, ArrayList<ActivityTable> actList) {
    ...
    inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}  

此外,您应该优化ListView的性能。

这是我的经验


仍然给我重复的视图,伙计。那我就使用RecyclerView了。 - Jay

1

把这3个放在正确的位置是很好的。

@Override
public int getCount() {
    return actList().size();
}

@Override
public Object getItem(int position) {
    return actList().get(position);
}

@Override
public long getItemId(int position) {
    return position;
}

这里是重要部分,首先您需要告诉适配器有多少种类型, 然后您需要告诉适配器如何确定类型。

这里我告诉类型视图类型=2

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

在这里,我告诉适配器如何将类型编号放入数组中。 我使用setType = 0 || setType = 1。 这是个人偏好:我喜欢使用int而不是String。

@Override
public int getItemViewType(int position) {
    return act.get(position).getType();
}

然后稍后在getView中。
@Override
public View getView(int position, View convertView, ViewGroup parent) {

    View v = convertView;
    int listViewItemType = getItemViewType(position);
    if (v == null) {
        ..whatevever you doing to make v not null
    }

    if (listViewItemType == 0) {
        //Do something    
    }else if(listViewItemType == 1){
       // Do something different 
    }
    return v;
}

0

是的,你会得到重复的项目,因为Convertview正在重用。一旦创建了convertview,如果你滚动,那个视图就会被重用。

所以最好使用单个布局,并且同时包含图像和文本。根据类型隐藏任何一个。


使用 setVisibility 对每个项目进行操作和使用两个不同的视图一样糟糕。如果您必须添加 5 个文本框并且必须隐藏 5 个文本框,那么在将来使用一个视图会很困难。我无法相信这是正确的答案。@earthling 最佳实践是将我的答案作为适配器识别两个视图之间差异的逻辑,然后使用视图持有者。我看到您在代码中使用了视图持有者,您应该能够理解这一点。 - NOT_A_PROGRAMMER

0

XML 文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >

<ImageView
    android:id="@+id/ImgFeed"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" />

<TextView
    android:id="@+id/txtCaption"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" />

</LinearLayout>

尝试使用TextView而不是ImageView

public View getView(int position, View convertView, ViewGroup parent) {

        Holder holder;

        final ActivityTable act = actList.get(position);
        inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if (convertView == null) {
        convertView = inflater.inflate(R.layout.feed_layout, null);
        holder = new Holder();
        holder.caption = (TextView) convertView.findViewById(R.id.txtCaption);
        holder.media = (ImageView) convertView.findViewById(R.id.ImgFeed);
            if (act.getType().equals("text")) {
                holder.media.setVisibility(View.GONE)
            }

            else if (act.getType().equals("photo")) {
                holder.caption.setVisibility(View.GONE)             
            }
            convertView.setTag(holder);

        } else {

            holder = (Holder) convertView.getTag();

        }

     return convertView;
}

你能澄清一下你的解决方案吗?我看不出有什么区别。 - Jay
holdor.caption 是 TextView,但你在 getView 中却将其用作 ImageView。 - Narendra Motwani

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