Question

I've been fooling around with Android but I'm stuck. I have a adapter class that sets an image in an imageview for each item in my gridView. I use the observer pattern to notify the activity that calls the update method and it refreshes the adapter with notifydatasetchanged and that invalidates the gridview itself and the imageView.

The problem is that when i change an object (which has a reference to a drawable), and try to update, nothing happens in the imageview. I've tried to debug and the objects are changed so i don't understand why it doesn't update...

Also, with this it works perfect to make the images disappear, so that's pretty akward..: shape.setImage(android.R.color.transparent)

@Override
    public void update(Observable arg0, Object arg1)
    {
    //  Toast.makeText(this, "I am notified",0).show();

        adapter.notifyDataSetChanged();
        gridView.findViewById(R.id.picture).invalidate();
        gridView.invalidate();

    }

This is an example of an object that needs to be showed:

public class Square extends Shape
{
    public Square()
    {
        setImage(R.drawable.square);
    }
    public String print()
    {
        return "s ";
    }
    public String getName()
    {
        return "Square";
    }
}

my adapter:

public class GridAdapter extends ArrayAdapter<Shape>
{
     Context context;
     int layoutResourceId;   
     List<Shape> data = null;



    public GridAdapter(Context context, int layoutResourceId, List<Shape> data)
     {
            super(context, layoutResourceId, data);
            this.layoutResourceId = layoutResourceId;
            this.context = context;
            this.data = data;
     }
     public View getView(int position, View convertView,ViewGroup parent) 
     {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

            View rowView = inflater.inflate(R.layout.list_item, parent, false);

            rowView.setBackgroundResource(R.drawable.customshape);

            ImageView imgView =(ImageView)rowView.findViewById(R.id.picture);

            imgView.setImageResource(data.get(position).getImage());

            return rowView;
     }
Était-ce utile?

La solution 4

Problem solved lol, i just made a new adapter instead and it worked

Autres conseils

I think the actual problem here is updating the drawable from outside the UI thread. notifyDataSetChanged() isn't the answer. The dataset didn't change, in my case at least. The dataset changed and I set the drawable to null (which worked). Later, when the image finished loading, I wasn't updating from the UI thread, so the GridView didn't know it was supposed to learn about the invalidation of the ImageView.

The answer in my case was to use AsyncTask which automatically uses the UI thread and thread syncs.

Note that notifyDatasetChanged() is for when the getViewId() changes in the adapter — which isn't the same as and actually has nothing to do with when the drawable changes. Also note that setImageDrawable() automatically invalidates the ImageView. There's actually no need to call ImageView.invalidate() or any other invalidate(). You just have to update the drawable in the UI thread, and AsyncTask comes with all the right baggage to not only do it at the right time, but in such a way that the GridView can learn about it before it updates the various canvases and drawable caches.

I learned most of the above from the Google Android dev pages and from source diving for hours on end. Curiously, source diving in Android Studio (ctrl-B) is actually easier than slogging through all the docs hoping to stumble on the right paragraph that explains the problem. Though, the problem is explained nicely here:

http://developer.android.com/training/displaying-bitmaps/process-bitmap.html

I cannot comment, so I am going to share my thoughts here, let me know in the comments if I'm missing something.

Seems like you need to add the following method in your GridAdapter:

public void setData(List<Shape> stuff) {
    data.clear();
    data.addAll(stuff);
    notifyDataSetChanged();
}

Now, wherever in your activity you created the adapter, you should have a List that was passed to create the GridAdapter. Let's call that initial list 'data1'.

Assuming by 'refresh' you mean that you want to modify an existing item. You need to find that item in data1 and make the changes. Then you need to find the GridAdapter instance that you have already created and then use the setData method and pass data1.

Hope this is not totally useless info for you.

Note: it would be helpful if you posted more of your code.

The problem is that when i change an object (which has a reference to a drawable), and try to update, nothing happens in the imageview.

Lets have a look at the doc:

public void notifyDataSetChanged()

Notifies the attached observers that the underlying data has been changed and any View reflecting the data set should refresh itself.

the only reason that when you call notifyDataSetChanged() and it dose not update your gridview is that your adapter data set and your object are two different things. that means your gridview data has not changed. you must change those objects that you passed to your gridView constructor (List data). if you change any of them and then you call notifyDataSetChanged() it will work. The references of your object and the adapter data must be the same.

another things that I have seen on the net is you must change the data set of adapter by manipulating it with functions like (add(), insert(), remove(), clear(), etc.).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top