自定义ArrayAdapter不更新子窗口小部件

时间:2012-04-20 13:03:54

标签: android

我遇到的问题是我的ListView的自定义ArrayAdapter,它有一个Gallery小部件和两个TextViews作为子级,不会更新Gallery小部件及其内容。

要设置应用程序的背景,我正在创建一个应用程序,允许两个或多个设备通过蓝牙相互连接,并将每个设备的照片流式传输到其连接的设备。现在,为了实现起见,每个设备都在一个可滚动的列表视图中表示,其中包含图库窗口小部件(所有设备的图像可以水平滚动)和下面的两个TextView窗口小部件,用于标识发件人。

ListView的布局如下:

<LinearLayout ...>
    <Gallery .../>
    <LinearLayout>
        <TextView .../>
        <TextView .../>
    </LinearLayout>
</LinearLayout>

图像发送和接收不是问题,我已经反复测试过它们。

问题似乎是自定义ArrayAdapter的notifyDataSetChanged()方法不按预期运行。当我在ListView中创建一个新的ImageHolderClass对象(在我的主Activity中)时,我按如下方式创建:mImageHolderAdapter.add(new ImageHolderClass(this, "Me", mBtAdapter.getAddress(), mLocalImageList));。知道适配器的add()方法应该调用notifyDataSetChanged(),它可以按照预期的方式为创建和添加的第一个对象工作。但是当我添加另一个对象或将任何新图像添加到对象的imageList时,它们会创建存储在第一个对象中的图像的精确副本。

现在,有趣的是每个ImageHolderClass中的两个TextView变量都会被更新,但是Gallery中的图像似乎保持完全相同。

我尝试绕过add()(使用ImageHolderAdapter())方法中的addItem()方法,然后仅在添加其他图片时强制notifyDataSetChanged(),似乎显示其他图像(但不显示所有图像),但不是仅当设备和其他设备没有连接时。

我的自定义ArrayAdapter如下:

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

}

以及上面使用的ImageHolderClass如下:

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

}

结果图像(两个ListView对象具有相同的图像(但不应该))可以在下图中看到: http://i.stack.imgur.com/koL2Q.jpg

我尝试使用自定义Gallery替换HorizontalListView窗口小部件,但这给了我完全相同的结果,所以我知道这不是由于Gallery窗口小部件实现。

更新

我修改了我的代码,将每个图片分别添加到ImageHolderAdapter。之前,我会创建一个ArrayList,将所有图像存储在其中,然后在ImageHolderAdapter中创建一个新对象。下面的方法显示了我将如何“批量”添加图像

public void loadImages(String userName, String deviceAddress, ArrayList imageList) {
    mImageHolderAdapterList.add(new ImageHolderClass(this, userName, deviceAddress, imageList));
    mImageHolderAdapter.notifyDataSetChanged();
}

现在,我在填充ImageHolderClass之前创建了imageList对象。然后,我从ImageHolderAdapter(使用mImageHolderAdapter.getItem(position))获取特定对象,从中获取imageListadd()获取ArrayList。每当我做出任何修改时,我都会致电mImageHolderAdapter.notifyDataSetChanged()

但是,如果我单独填充图像,则现在不显示任何图像。我得到的只是一个黑屏,图像应该是。

2 个答案:

答案 0 :(得分:1)

您应该在if语句之外设置图库的适配器。

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.deviceName = (TextView)v.findViewById(R.id.deviceName);
    holder.deviceAddress = (TextView)v.findViewById(R.id.deviceAddress);
    v.setTag(holder);
} else {
    holder = (ViewHolder)v.getTag();
}

holder.gallery.setAdapter(new ImageAdapter(getContext(), objects.get(position).imageList));

答案 1 :(得分:0)

Updating the list view when the adapter data changes

尝试使视图或适配器无效(notifyDataSetChanged())...