3

I'm basically trying to display multiple views via the same ListView adapter. However, the adapter ends up generating multiple duplicates and crashes sometimes as well with a NullPointer. My guess is that I have implemented the adapter all wrong. Here's my complete code:

The item could either be a photo or a text.

Adapter:

 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;
    }
}

Am I inflating multiple views in the same adapter the wrong way? Can anyone point out the error?

Jay
  • 4,873
  • 7
  • 72
  • 137

4 Answers4

1

You have 2 diffrent layout for each row so I think you should add

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

to your listview adapter
In your code, try to initial your LayoutInflater inside the constructor of your adapter

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

And also you should optimize your ListView performance

Here is my experience

Community
  • 1
  • 1
Linh
  • 57,942
  • 23
  • 262
  • 279
1

It is good to have these 3 in place.

@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;
}

Here is the important part, first you have to tell the adapter how many type, and then you have to tell the adapter how to determine the type.

Here I tell type View Type = 2

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

and Here I tell the adapter How I put the type number into the array I use setType = 0 || set Type = 1 personal preference here: I like to use int instead of String

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

and then later at the 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;
}
NOT_A_PROGRAMMER
  • 1,794
  • 2
  • 20
  • 31
0

xml file

<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>

try this you are using ImageView insted of TextView

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;
}
Narendra Motwani
  • 1,085
  • 10
  • 20
0

Yes you will get duplicate Item, Because Convertview is reusing. Once convertview is created that view using if you scroll.

So better use single layout and with both Image and text. Based type hide any one.

Ramesh
  • 54
  • 4
  • using setVisibility for each item is as bad as using two different view. Good luck using one view in the future, if you have to add 5 textboxes and you have to hide 5 textboxes. I can not believe this is a correct answer. @earthling the best practice is using my answer as the logic for adpater to identify the different between two views and then use view Holder, I see you use view Holder in your code. you should be able to understand that. – NOT_A_PROGRAMMER Dec 24 '15 at 14:51