Mike
Mike

Reputation: 857

ListView using multiple Subitems

Hello and again a question about a List this time.. a ListView......

I'm using a BaseAdapter to inflate a layout which includes a RelativeLayout(Parent) and 4 ImagesViews which are alignBaseline(horizontal) to the first ImageView.(It doesn't really matter) They all have the same source, which is an imageArray. The Problem is that the getView-Method only fires for every ListItem created/reused/scrolled into the view..but not for the childs of the ListItem(my ImageViews). So as you already expected:"How can he set the Images to the ImageViews from the same source if getView only fires for every listItem, but not for the childrens of every listitem??".

I stucked here:

public View getView(final int position, View convertView, ViewGroup parent) {
    // TODO Auto-generated method stub
    ImageView img1;
    ImageView img2;
    ImageView img3;
    ImageView img4;
    TextView tv1;
    TextView tv2;
    TextView tv3;
    TextView tv4;
    TextView tv_abc;

    if(convertView == null) {
        convertView = inflater.inflate(R.layout.customadapter_view_layout, null);
        img1 = (ImageView) convertView.findViewById(R.id.img_normal_portrait_1);
        img2 = (ImageView) convertView.findViewById(R.id.img_normal_portrait_2);
        img3 = (ImageView) convertView.findViewById(R.id.img_normal_portrait_3);
        img4 = (ImageView) convertView.findViewById(R.id.img_normal_portrait_4);
        tv1 =(TextView) convertView.findViewById(R.id.tv_normal_portrait_1);
        tv2 =(TextView) convertView.findViewById(R.id.tv_normal_portrait_2);
        tv3 =(TextView) convertView.findViewById(R.id.tv_normal_portrait_3);
        tv4 =(TextView) convertView.findViewById(R.id.tv_normal_portrait_4);
        tv_abc = (TextView) convertView.findViewById(R.id.tv_normal_portrait_abc);
        convertView.setTag(new Holder(img1,img2,img3,img4,tv1, tv2, tv3, tv4,tv_abc));
    } else {
        Holder holder = (Holder) convertView.getTag();
        img1 = holder.img1;
        img2 = holder.img2;
        img3 = holder.img3;
        img4 = holder.img4;
        tv1 = holder.tv1;
        tv2 = holder.tv2;
        tv3 = holder.tv3;
        tv4 = holder.tv4;
        tv_abc = holder.tv_abc;

    }
        img1.setImageDrawable(scaledImage[position]);
        img2.setImageDrawable(scaledImage[position+1]);
        img3.setImageDrawable(scaledImage[position+2]);
        img4.setImageDrawable(scaledImage[position+3]);
        tv1.setText(labels[position]);
        tv2.setText(labels[position+1]);
        tv3.setText(labels[position+2]);
        tv4.setText(labels[position+3]);


    return convertView;
}

}

(Please ignore the textViews) As you already mentioned, this is extremly slow and it doesn't even work. Why? As i mentioned before, Position(from getView) Counts every ListItem but not every Child of the Listitem. Furthermore when i tried this i found out that Position(from getView) only Counts ListItems. And later i thought, how could i be that stupid thinking that the getView knows(or better wants to know) about the Childs in my layout ?? Even more i hate Solutions like that above...they are slow, complicated and often lead into IndexOutOfBoundException.

So please, do someone have a much better solution or a totally different way getting this work.(Other Adapter, whatever). I appreciate every help. Thank you

Upvotes: 0

Views: 304

Answers (1)

Ifrit
Ifrit

Reputation: 6821

POJO

POJO is actually a java programming term and not necessarily associated only with Android. It stands for Plain Old Java Object and many other languages have their own equivalent acronym. Wikipedia has a nice write up about it. The idea is needing a very simple class to pass around some data. The Holder you are using is an example of a POJO.

Counting

As you mentioned, part of your problem is an slight mistake in understanding how a BaseAdapter works. I'm assuming you had defined the following:

@Override
public int getCount() {
    return scaledImage.length();
}

When in reality you needed something more like:

@Override
public int getCount() {
    //This assumes you'll ensure the array will always be equally divisible by 4.
    //If not, you'll need to add some empty elements at the end to make it so.
    return scaledImage.length() / 4;
}

The adapter is only aware of the number of rows it contains and not how much data in total is used for the rows. Receiving IndexOutOfBoundsExpections is not the result of using scaledImage as shown in your code. It's a problem caused elsewhere. Using an array like that is perfectly fine...so long as your getCount() method is returning the correct value.

Applying POJO

As Chitrang has suggested, you could convert your scaledImage array into a POJO. So for example, you'd have something like:

private class ScaledImageRow {
    //You could just as easily use an array of 4 elements instead
    Drawable image1;
    Drawable image2;
    Drawable image3;
    Drawable image4;
}

Then when you are constructing your custom adapter, you'd want to convert your:

Drawable[] scaledImage;

into a:

ScaledImageRow[] scaledImageRow;

By doing this, you can then return the length of the scaledImageRow for the count and in your getView() obtained the correct row of images by using scaledImageRow[position]

Now converting your data over to such a POJO doesn't really by you anything performance wise. What it does more so is increase the readability of your code. It will also help conceptualize what's going on with your code better.

Performance

You mentioned some very slow performance with your getView() as depicted in answer. Your array approach is definitely not the cause of it. I would say it's the setting of the images. I'm guessing you've already loaded the images into memory. So perhaps the images are still fairly large and the ImageView has some sort of scaling attribute defined in XML? Otherwise, I'd say the slowdown is being caused elsewhere in your code.

Upvotes: 1

Related Questions