0

I have a custom ArrayAdapter that is used to place icons within lists

public class IconArrayAdapter extends ArrayAdapter<IconListItem> {

    protected int resource;

    public IconArrayAdapter(Context context, int resource, ArrayList<IconListItem> items) {
        super(context, resource, items);
        this.resource = resource;
    }

    public IconArrayAdapter(Context context, ArrayList<IconListItem> items) {
        super(context, R.layout.icon_list_item, items);
        this.resource =  R.layout.icon_list_item;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        IconListItem iconItem = getItem(position);
        if (convertView == null) {
            convertView = LayoutInflater.from(getContext()).inflate(this.resource, null);
        }

        ...

        return convertView;
    }
}

This is a generic adapter I use in multiple part of my app that I need to extend a little bit in one spot for a more specific purpose. I started building the extended class but immediatley ran into a problem

public class TeamListArrayAdapter extends IconArrayAdapter {

    public TeamListArrayAdapter(Context context, ArrayList<TeamListItem> items) {
        super(context, R.layout.team_list_item, items);
    }

}

Despite TeamListItem extending IconListItem, I am unable to pass the items into the super. From my understanding, because TeamListItem extends IconListItem I should be able to pass that, but clearly I can't. What am I misunderstanding here?

Edit: I guess I'm a little confused because I can easily do things like:

private class Object1 {
    protected int property1 = 1;
}

private class Object2 extends Object1 {
    protected int property2 = 2;
}

ArrayList<Object1> objects = new ArrayList<Object1>();
objects.add(new Object2());

With no problem.

Edit 2: Added a code for the IconArrayAdapter that has the private bits removed.

Devin Rodriguez
  • 1,144
  • 1
  • 13
  • 30

3 Answers3

1

Inheritance doesn't work like you are hoping it does when you are talking about parameterized types:

  • Even if S is a proper subtype of T
  • Then List<S> is not a subtype of List<T>

Therefore you cannot pass a List<TeamListItem> as an argument where the parameter is of type List<IconListItem>.

But, you can get around this in your case by doing:

public TeamListArrayAdapter(Context context, ArrayList<TeamListItem> items) {
  super(context, R.layout.team_list_item, new ArrayList<IconListItem>(items));
}

This just copies all the items from the List<TeamListItem> into a new List<IconListItem>, and then passes the latter as the argument to the supertype constructor.

EDIT: based on your question edit, I think you might be able to do this:

public class IconArrayAdapter<T extends IconListItem> extends ArrayAdapter<T> {
  protected int resource;
  public IconArrayAdapter(Context context, int resource, ArrayList<T> items) {
      super(context, resource, items);
      this.resource = resource;
  }
}

public class TeamListArrayAdapter extends IconArrayAdapter<TeamListItem> {
  public TeamListArrayAdapter(Context context, ArrayList<TeamListItem> items) {
      super(context, R.layout.team_list_item, items);
  }
}
Andy Brown
  • 18,961
  • 3
  • 52
  • 62
  • This makes a lot of sense. So in this case, would it destroy extended properties of the items or would they still be available if I cast each item to TeamListItem later? – Devin Rodriguez Feb 21 '15 at 23:12
  • @DevinRodriguez. The items are still of type `TeamListItem` (so all their state as such is preserved), but they are now held in a type that treats them as `IconListItem`. This may actually cause you other problems (such as risky downcasting to return the items as `TeamListItem`s later), so maybe you should rethink what you are trying to achieve and how you are designing this. – Andy Brown Feb 21 '15 at 23:15
  • I've posted more of the code to the `IconArrayAdapter` for review. What I'm trying to achieve is that in the list of team members additional information needs to be shown. The team list item is almost the exact same as the icon list items, with an additional block of text that needs to be filled in, so I was hoping to extend my existing class and make the needed updates in the getView rather than clone the whole class for this one purpose. – Devin Rodriguez Feb 21 '15 at 23:21
  • @DevinRodriguez. Updated answer, try that. – Andy Brown Feb 21 '15 at 23:31
  • Giving it a shot, got another bug that's preventing me from getting to that part of my app right now. – Devin Rodriguez Feb 21 '15 at 23:32
  • That worked perfectly, even already implemented the extra data. Thanks for the help! – Devin Rodriguez Feb 21 '15 at 23:52
  • @DevinRodriguez. No problem, and thank you for making my 10,000 (and 10). – Andy Brown Feb 21 '15 at 23:53
0

The super-class of TeamListArrayAdapter is IconArrayAdapter. You are trying to pass ArrayList<TeamListItem> items as a parameter in your super(...) constructor call, but IconArrayAdapter doesn't have any constructor that takes in ArrayList<TeamListItem> items as a parameter.

Please give us your full code of IconArrayAdapter and tell us your initial goal. Why are you extending this class and etc?

If TeamListItem inherited IconListItem you could have done your approach. Similar to your Object-class example.

knordbo
  • 552
  • 3
  • 7
-1

Perhaps you need to have

public IconArrayAdapter(Context context, ArrayList<? extends IconListItem> items) 
{
    super(context, R.layout.team_list_item);
}

And then your TeamListArrayAdapter ctor should be fine.

Vino
  • 1,544
  • 1
  • 18
  • 26
  • The [constructor of `ArrayAdapter`](http://developer.android.com/reference/android/widget/ArrayAdapter.html) is `ArrayAdapter(Context context, int resource, List objects)` so this won't work. You'll now get a compiler error that no constructor can be found that accepts the capture type. – Andy Brown Feb 21 '15 at 23:18
  • @AndyBrown Not quite. ArrayAdapter also has a constructor that takes just a Context and an int. Just FYI. – Mike M. Feb 21 '15 at 23:27
  • @MikeM. Yes, but I'm ignoring that as I'm assuming that Vino did actually mean to use the `items` parameter in the call to `super`, despite omitting the argument in the call. – Andy Brown Feb 21 '15 at 23:34