I'm having an issue where my custom ArrayAdapter for my ListView, which has a Gallery widget and two TextViews as children, isn't updating the Gallery widget and its contents.
To set the background for the application, I'm creating an application that allows two or more devices to connect to one another via Bluetooth and streams each device's photos to its connected devices. Right now, just for implementation's sake, each device is represented in a scrollable list view, which contains the gallery widget (with all that device's images scrollable in a horizontal manner) and two TextView widgets below it, identifying the senders.
The layout for the ListView is as follows:
<LinearLayout ...>
<Gallery .../>
<LinearLayout>
<TextView .../>
<TextView .../>
</LinearLayout>
</LinearLayout>
The image sending and receiving aren't the problem and I have tested them quite repeatedly.
The problem seems to be with the custom ArrayAdapter's notifyDataSetChanged()
method not behaving as expected. When I create a new ImageHolderClass object in the ListView (in my main Activity
), I do so as follows: mImageHolderAdapter.add(new ImageHolderClass(this, "Me", mBtAdapter.getAddress(), mLocalImageList));
. Knowing that the add()
method for the adapter should be calling notifyDataSetChanged()
, it works as expected for the first object created and added. But when I add another object or add any new images to the object's imageList
, they create an exact copy of the images stored in the first object.
Now, the interesting thing is that the two TextView variables in each ImageHolderClass
manages to be updated, but the images in the Gallery seems to stay exactly the same.
I've tried bypassing the add()
method in the ImageHolderAdapter()
(with a addItem()
) method, and then forcing a notifyDataSetChanged()
only when other images are added, which seems to show the other images (but doesn't display all of them), but not when only the device and no other devices are connected.
my custom ArrayAdapter is as follows:
public class ImageHolderAdapter extends ArrayAdapter<ImageHolderClass>{
private ArrayList<ImageHolderClass> objects;
public ImageHolderAdapter(Context context, int layoutResourceId, ArrayList<ImageHolderClass> objects) {
super(context, layoutResourceId, objects);
this.objects = objects;
}
public static class ViewHolder {
public Gallery gallery;
public TextView deviceName;
public TextView deviceAddress;
public ArrayList imageList;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// Assign the view we are converting to a local variable
View v = convertView;
ViewHolder holder;
// first check to see if the view is null. If it is, then we have to inflate it.
if (v == null) {
LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.imageholder, null);
holder = new ViewHolder();
holder.gallery = (Gallery)v.findViewById(R.id.gallery);
holder.gallery.setAdapter(new ImageAdapter(getContext(), objects.get(position).imageList));
holder.deviceName = (TextView)v.findViewById(R.id.deviceName);
holder.deviceAddress = (TextView)v.findViewById(R.id.deviceAddress);
v.setTag(holder);
} else {
holder = (ViewHolder)v.getTag();
}
final ImageHolderClass imageHolderClass = objects.get(position);
if (imageHolderClass != null) {
holder.gallery = imageHolderClass.getGallery();
holder.deviceName.setText(imageHolderClass.getDeviceName());
holder.deviceAddress.setText(imageHolderClass.getDeviceAddress());
}
return v;
}
public class ImageAdapter extends BaseAdapter {
int mGalleryItemBackground;
private Context mContext;
ArrayList list;
public ImageAdapter(Context c, ArrayList list) {
mContext = c;
this.list = list;
TypedArray attr = mContext.obtainStyledAttributes(R.styleable.TestbedActivity);
mGalleryItemBackground = attr.getResourceId(R.styleable.TestbedActivity_android_galleryItemBackground, 0);
attr.recycle();
}
public int getCount() {
return list.size();
}
public Object getItem(int position) {
return list.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = new ImageView(mContext);
imageView.setImageBitmap((Bitmap)list.get(position));
imageView.setLayoutParams(new Gallery.LayoutParams(180, 150));
imageView.setScaleType(ImageView.ScaleType.FIT_XY);
imageView.setBackgroundResource(mGalleryItemBackground);
return imageView;
}
}
}
and the ImageHolderClass, which is used above is as follows:
public class ImageHolderClass {
public Gallery gallery;
public String deviceName;
public String deviceAddress;
public ArrayList imageList;
public ImageHolderClass() {
super();
}
public ImageHolderClass(Context c, String deviceName, String deviceAddress, ArrayList imageList) {
super();
this.gallery = new Gallery(c);
this.deviceName = deviceName;
this.deviceAddress = deviceAddress;
this.imageList = imageList;
}
public Gallery getGallery() {
return gallery;
}
public void setGallery(Gallery gallery) {
this.gallery = gallery;
}
public String getDeviceName() {
return deviceName;
}
public void setDeviceName(String deviceName) {
this.deviceName = deviceName;
}
public String getDeviceAddress() {
return deviceAddress;
}
public void setDeviceAddress(String deviceAddress) {
this.deviceAddress = deviceAddress;
}
public void setImageList(ArrayList list) {
this.imageList = list;
}
public ArrayList getImageList() {
return imageList;
}
}
The resulting image (where both ListView objects have the same images (but shouldn't)) can be seen in the following image: https://i.stack.imgur.com/koL2Q.jpg
I've tried swapping out the Gallery
widget with a custom HorizontalListView
, but that gave me the exact same result, so I know it wasn't due to the Gallery
widgets implementation.
Update
I've modified my code to add each image individually to the ImageHolderAdapter
. Before, I would create a ArrayList
, store all my images in it and then create a new object in ImageHolderAdapter
. The method below shows how I would add images "in bulk"
public void loadImages(String userName, String deviceAddress, ArrayList imageList) {
mImageHolderAdapterList.add(new ImageHolderClass(this, userName, deviceAddress, imageList));
mImageHolderAdapter.notifyDataSetChanged();
}
Now, I create the ImageHolderClass
object before I populate the imageList
. I then grab the specific object out from the ImageHolderAdapter
(by using mImageHolderAdapter.getItem(position)
), get the imageList
from that and add()
to the ArrayList
. I then call mImageHolderAdapter.notifyDataSetChanged()
whenever I've made any modifications.
However, no images are now being displayed if I populate the images individually. All I get is a black screen where the images should be.