【问题标题】:Custom ArrayAdapter not updating children widgets自定义 ArrayAdapter 不更新子小部件
【发布时间】:2012-04-20 13:03:53
【问题描述】:

我遇到了一个问题,即我的 ListView 的自定义 ArrayAdapter 没有更新 Gallery 小部件及其内容,它有一个 Gallery 小部件和两个 TextView 作为子项。

为了设置应用程序的背景,我正在创建一个应用程序,该应用程序允许两个或多个设备通过蓝牙相互连接,并将每个设备的照片流式传输到其连接的设备。现在,只是为了实现,每个设备都显示在一个可滚动的列表视图中,其中包含画廊小部件(该设备的所有图像都可以水平滚动)和它下方的两个 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 中的图像似乎保持不变。

我尝试在ImageHolderAdapter()(使用addItem())方法中绕过add() 方法,然后仅在添加其他图像时才强制使用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

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

更新

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

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

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

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

【问题讨论】:

    标签: android


    【解决方案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));
    

    【讨论】:

      【解决方案2】:

      Updating the list view when the adapter data changes

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-04-22
        • 1970-01-01
        • 1970-01-01
        • 2013-08-05
        • 1970-01-01
        • 1970-01-01
        • 2020-01-08
        • 2021-11-22
        相关资源
        最近更新 更多