Reputation: 857
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
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