Question

I'm trying to implement a custom type of ListAdapter. The underlying data can come from either a database or some other type of data source, which means I should extend BaseAdapter. However, I also want to use the existing logic that is implemented in SimpleCursorAdapter and SimpleAdapter.

I guess one way of putting it is that i want to "inject" a new class between BaseAdapter and it's decendants...

Basically what I want to acheive is something like this diagram, just to illustrate the probem.

Below is one possible solution I came up with, but I'm curious about what the standard way of doing something like this would be?

public class ExpandableAdapterHelper{

    public void onNewView(View view, long id) {
        // Do stuff
    }

    public void onBindView(View view, long id) {
        // Do stuff
    }

}


public class ExpandableCursorAdapter extends SimpleCursorAdapter{           
        private ExpandableAdapterHelper expandableAdapterHelper;

        public ExpandableCursorAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) {
            super( context, layout, c, from, to, flags );
            expandableAdapterHelper = new ExpandableAdapterHelper();        
        }

        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            View newItem = super.newView(context, cursor, parent);
            expandableAdapterHelper.onNewView(newItem, cursor.getInt(0));
            return newItem;
        }

        @Override
        public void bindView(View view, Context context, Cursor cursor) {
            super.bindView(view, context, cursor);
            expandableAdapterHelper.onBindView(view, cursor.getInt(0));
        }                               
}



public class ExpandableSimpleAdapter extends SimpleAdapter{
    private ExpandableAdapterHelper expandableAdapterHelper;

    public ExpandableSimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to){
        super( context, data, resource, from, to );
        expandableAdapterHelper = new ExpandableAdapterHelper();
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if( convertView == null ){
            expandableAdapterHelper.onNewView(convertView, getItemId(position));
        }
        else{
            expandableAdapterHelper.onBindView(convertView, getItemId(position));
        }           

        return convertView;
    }
}
Was it helpful?

Solution

Here are your 3 options: 1- pick adapter type dynamically based on data, 2- convert data from one type to another 3- implement an adapter that reads multiple data types.

Option 1, pick adapter dynamically. - Sounds like the easiest solution, unless something is preventing you from doing this -- like having to display data from 2 sources simultaneously.

Option 2, convert data. - Also good solution. It's easy to read a cursor into a list or map imo, and then just implement one adapter that reads mapped data. @Luksprog has also made an option 2 solution - which is to instead feed simpleCursorAdapter a MatrixCursor that has your other data. But either way, you're converting your data to a uniform type.

Option 3, teach adaper to read multiple data types. - This is more complicated, but seems to be the "answer" to your question framed as teaching your adapter to read multiple data types. For this, simpleCursorAdapter doesn't seem a solution to me, because it doesn't give you control over the Views -- it internally binds cursor columns to view elements by matching resource Id's. Thus it's a poor choice for teaching how to read non-cursor data. If you go this route, I think the only option is the non-cursor adapters, like baseAdapter.

But again, solutions 1-2 are preferable. If you need option 3, then I would use a baseAdapter

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top