Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic adapter for many kinds of listview 's layout row in android

For each list view with difference row layout template, I must create each custom adapter, which do the same thing: load xml row layout, get control (TextView, ImageView, etc..) by id, display data... something like this:

public class CommentAdapter extends BaseAdapter {

protected Activity activity;
protected static LayoutInflater layoutInflater = null;  
protected List<Comment> lst;    

public CommentAdapter(Activity activity,  List<Comment> lst){
    this.activity = activity;       
    this.lst = lst;
    layoutInflater = (LayoutInflater)this.activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

public int getCount() {     
    return lst.size();
}

public Object getItem(int position) {   
    return lst.get(position);
}

public long getItemId(int position) {   
    return position;
}

public static class ViewHolder{
    public TextView textName;
    public TextView textComment;
    public ImageView image;
}

public  View getView(int position, View convertView, ViewGroup parent) {
    View v = convertView;
    ViewHolder viewHolder;
    if (v == null) {
        v = layoutInflater.inflate(R.layout.listitem, null);
        viewHolder = new ViewHolder();
        viewHolder.textName = (TextView) v.findViewById(R.id.txtName);
        viewHolder.image = (ImageView) v.findViewById(R.id.icon);
        viewHolder.textComment = (TextView)v.findViewById(R.id.txtComment);
        v.setTag(viewHolder);
    } else {
        viewHolder = (ViewHolder) v.getTag();
    }
    Static.overrideFonts(v);
    viewHolder.image.setBackgroundResource(lst.get(position).Icon);
    viewHolder.textName.setText(lst.get(position).Name);
    viewHolder.textComment.setText(lst.get(position).Comment);

    return v;
}
}

With many kind of list view (difference row layout template), I have to create many adapters.
So, the question is that I want to create one template adapter, which can be dynamic load row xml, map view control base on its id (maybe use reflect). The row xml layout, the control id, view control will be defined in another places.
Is there any design pattern, example or framework can achieve this?

like image 904
ductran Avatar asked Oct 24 '12 17:10

ductran


1 Answers

Something like this seems doable. I haven't tested this at all, but in theory you could get away with something like this:

public interface Adaptable {
    //Interface that any object you make that should be put in a listview
    //should implement
    public View buildView(View v, LayoutInflater inflater);
    public int getLayoutId();
}

public class MyObject implements Adaptable
    //Just hardcode your layout for this type of object
    public int getLayoutId() {
        return R.layout.myLayout;
    }

    //getView() will pass the recycled view to this method
    //which will handle building the view per this object
    public View buildView(View v, LayoutInflater inflater) {
        if(v == null) {
            v = inflater.inflate(getLayoutId());
            //Other initialization
        } //other initialization

        return v;
    }
}

//Then make the generic adapter that handles anything that implements
//the Adaptable interface
public GenericAdapter implements ListAdapter {
    private LayoutInflater inflater;
    private List<Adaptable> items;
    public GenericAdapter(List<Adaptable> items, Context c) {
        this.items = items;
        inflater = LayoutInflater.from(c);
    }

    //Now, using polymorphism, it should return a correctly built
    //view for whatever object type you've passed in.
    @Override
    public View getView(int pos, View convertView, ViewGroup parent) {
        return items.get(pos).buildView(convertView, inflater);
    }
}

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    List<MyObject> objects = new ArrayList<MyObject>();
    //Fill your list however.

    //get your ListView, then...
    listView.setAdapter(new GenericAdapter(object, this));
}

It's possible I've totally overlooked some reason this wouldn't work -- I typed this up in five minutes. In theory I think it would work, though.

like image 53
Kevin Coppock Avatar answered Oct 20 '22 13:10

Kevin Coppock