0

My app needs to be able to change the drawables displayed in a gridview, mainly just colours and some of the information displayed. The different styles have different .java and XML files.

The different .java files are used for displaying different types of the same thing, and so inherit from a shared parent, for example basicrunner extends runner and lollipoprunner extends runner.

The adapter extends BaseAdapter, and overrides the methods for getItem etc, but they specify one return type;

public class RunnersAdapter extends BaseAdapter {
private static final String TAG = "RunnersAdapter";

//used in switch statement to decide which XML to inflate
private static final int LayoutTYPE_1 = 1;  
private static final int LayoutTYPE_2 = 2;
private static final int LayoutTYPE_3 = 3;
int layout = 2; //hard coded just for testing

@Override
public Runner getItem(int position) { //runner is superclass
    return mRunners.get(mKeys[position]);
}

Is there a way to use this one RunnersAdapter for each type of runner, or am I better off making a different adapter for each type?

EDIT:

This is an upgrade from an adapter that only ever needed to display one data type, namely Runner. Now we want to display multiple different types of runners, but not necessarily make multiple types of adapters.

Some more code to illustrate what I mean:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    LayoutInflater inflater = (LayoutInflater) mContext
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

if(layout == LayoutTYPE_1){ //LollipopView

            Runner runner = getItem(position); //should be a lollipopRunner!!

            gridView = inflater.inflate(R.layout.lollipopRunner, null); //use lollipopRunner XML
}else if(layout == LayoutTYPE_2){

            Runner runner = getItem(position);  //should be basicRunner!!

            gridView = inflater.inflate(R.layout.basicrunner, null); //use basic runner XML

As shown above, the overridden getItem method returns type "Runner", which is the parent class of BasicRunner and LollipopRunner.

Is there a correct application of polymorphism that would allow this to work? Do I need new adapters for each Runner?

Richardweber32
  • 168
  • 2
  • 16
  • [might this fix your issue?](https://stackoverflow.com/a/38350061/4700782) – Pier Giorgio Misley Sep 18 '17 at 14:32
  • so the view type in your gridview is the same but only differs in different drawables used? or each item can have different view type attached? – pskink Sep 18 '17 at 14:36
  • @pskink Yeah each item in the gridview will be of the same type, ie all basicRunner or all lollipopRunner. The drawables change and so does the data types. I'll edit my OP to include some more code – Richardweber32 Sep 18 '17 at 15:13
  • i was asking if the same view will be shown for every item - for example only `TextView` with different content / background drawable or different views will be used – pskink Sep 18 '17 at 15:15
  • I see, yes it'll only be displayed in a gridView. No changing of views, just the drawables and the java classes associated with them – Richardweber32 Sep 18 '17 at 15:25

2 Answers2

1

BaseAdapter has few method that you can override in order to return different type of view based on position.

Those are:

        @Override
        public int getItemViewType(int position) {
            if (...) return 1;
            else if (...) return 2;
            else if (...) return 3;
            else return 4;
        }

        @Override
        public int getViewTypeCount() {
            return 4; //total number of different type of views 
        }


        @Override
        public View getView(int position, View view, ViewGroup viewGroup) {


            switch (getItemViewType(position)) {
                case 0:
                    if (view == null) {
                        view = mActivity.getLayoutInflater().inflate(R.layout.message_item_1, viewGroup, false);
                    }
                    break;
                case 1:
                    if (view == null) {
                        view = mActivity.getLayoutInflater().inflate(R.layout.message_item_1_media, viewGroup, false);
                    }
                    break;
                case 2:
                    if (view == null) {
                        view = mActivity.getLayoutInflater().inflate(R.layout.message_item_2, viewGroup, false);
                    }
                    break;
                case 3:
                    if (view == null) {
                        view = mActivity.getLayoutInflater().inflate(R.layout.message_item_2_media, viewGroup, false);
                    }
                    break;
            }
    }

EDIT:

While feeding the data to your adapter, you can pass it as List of Object which you can later downcast as per your type.

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    LayoutInflater inflater = (LayoutInflater) mContext
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);

if(layout == LayoutTYPE_1){ //LollipopView

            // getItem(postion) will give you Object - downcast it as per the position.

            Runner runner = (LollipopRunner)(getItem(position)); //downcast to lollipopRunner

            gridView = inflater.inflate(R.layout.lollipopRunner, null); //use lollipopRunner XML
}else if(layout == LayoutTYPE_2){

            Runner runner = (BasicRunner)(getItem(position));  //downcasted to basic runner

        gridView = inflater.inflate(R.layout.basicrunner, null); //use basic runner XML
Sumit Jha
  • 2,095
  • 2
  • 21
  • 36
  • Correct me if I'm wrong, but this will allow me to use multiple xml files for one adapter but not multiple data types. Each XML file deals with a different type of runner, lollipopRunner and basicRunner for example. These have different functionality beyond just what is displayed. – Richardweber32 Sep 18 '17 at 14:44
  • Hello Sumit, thanks for your time. I had hoped to avoid downcasting but it looks like I would need to do a bit of restructuring. I will try yours and see what happens :) – Richardweber32 Sep 19 '17 at 09:25
  • you are welcome @Richardweber32 . Please upvote and mark as accepted if this answer helped you. It encourages developers to answer more thereby expanding the community. – Sumit Jha Sep 19 '17 at 14:44
0

When you declare the adapter you can try adding runners as parameter in the constructor part of your Adapter. Then getItem will return the runner in position.