Menu

RowAdapter - Android Adapters Made Simple

By Luke Deighton

RowAdapter is an Open Source Library to simplify writing code for adapters. It aims to provide a bridge between the old and the new, an "Adapter of Adapters". It provides a common API to work with the various Adapter implementations. It also provides further encapsulation by handling View Types meaning that your Adapter Code can be reused in one or many different adapters without the need to worry about View Type Counts.

The RowAdapter library focuses solely on binding data to views. It can be used for either a ListView, RecyclerView or ExpandableListView with an option to use the View Holder pattern. It gives the possibility of starting with a ListView and then converting to RecyclerView as it becomes more roboust, without requiring many changes to your code.

The basic usage of the library involves creating 'RowTypes' that know how to bind a particular set of data to a set of views. The interface should seem relatively familiar!

View createView(LayoutInflater inflater, ViewGroup parent, int position);
void bindView(View view, int position);

Most of the time you can use any subtype of the interface with a few exceptions including the RecyclerView, which enforces the View Holder pattern and therefore requires a sub type of ViewHolderRow. The createView method gives you the option to inflate or instantiate a new View and place any first time initialisation code here, such as setting a custom typeface (although you should really be using a custom textview/library to handle typefaces). The bindView method is where you recycle a previous view and bind the data to the view.

RowAdapter

Firstly create your own class that implements RowType (or a subtype). InflatedRow automatically inflates a layout from resources and requires a layout in its constructor. Only the bindView method requires code and getItem() can be called to retrieve the data.

public class SimpleTextRow extends InflatedRow<String> {
  private int mTextViewResId;

  public SimpleTextRow(String item, @LayoutRes int layoutResId, @IdRes int textViewResId) { 
    super(item, layoutResId);
    mTextViewResId = textViewResId;
  }

  @Override 
  public void bindView(View view, int position) { 
    ((TextView) view.findViewById(mTextViewResId)).setText(getItem()); 
  }
}

Once you have created your RowTypes you can simply build up your rows as a List<RowType> or using the RowBuilder class:

RowBuilder rowBuilder = new RowBuilder()
 .add(new HeaderRow("hello"))
 .add(new SimpleTextRow("simple", R.layout.row_header, R.id.textview))
 .add(new ImageResourceRow(R.drawable.ic_launcher));

Finally instantiate a RowAdapter with your list of rows:

mAdapter = new RowAdapter(this, rowBuilder.build());
mListView.setAdapter(mAdapter);

Notice how the library doesn't care about ViewTypeCount as it will figure out this information itself by comparing the classes' hash of each item in the list, i.e. A different class represents a different ViewType.

OnItemClickListener

Item Click Events can be handled in the traditional way by doing a combination of instanceof checks and casting to retrieve your selected data or by using the OnRowClickListener:

RowClickHandler clickHandler = new RowClickHandler()
.put(HeaderRow.class, new OnRowClickListener<HeaderRow>() {
 @Override
 public void onRowClick(HeaderRow typedRow, int position) {
  Toast.makeText(MainActivity.this, "header: " + typedRow.getItem(),   Toast.LENGTH_SHORT).show();
 }
})
.put(ImageResourceRow.class, new OnRowClickListener<ImageResourceRow>() {
 @Override
 public void onRowClick(ImageResourceRow typedRow, int position) {
  Toast.makeText(MainActivity.this, "image: " +   typedRow.getItem(), Toast.LENGTH_SHORT).show();
 }
})
.put(SimpleTextRow.class, new OnRowClickListener<SimpleTextRow>() {
 @Override
 public void onRowClick(SimpleTextRow typedRow, int position) {
  Toast.makeText(MainActivity.this, "simple: " + typedRow.getItem(),   Toast.LENGTH_SHORT).show();
 }
});
mListView.setOnItemClickListener(clickHandler);

RecyclerRowAdapter

The library also supports using the new RecyclerView Library. It works in a similar fashion to the above example but requires subtyping from ViewHolderRow with the second generic parameter extending RecyclerView.ViewHolder. A simple usage is shown in the next code snippet.

public class RecyclerRow extends ViewHolderRow<String, RecyclerRow.ViewHolder> {
 public RecyclerRow(String item) {
  super(item, R.layout.row_header);
 }
 @Override
 public ViewHolder createViewHolder(View view, int position) {
  return new ViewHolder(view);
 }
 @Override
 public void bindViewHolder(ViewHolder viewHolder, String item, int position) {
  viewHolder.mTextView.setText(item);
 }
 static class ViewHolder extends RecyclerView.ViewHolder {
  TextView mTextView;
  ViewHolder(View view) {
   super(view);
   mTextView = (TextView) view.findViewById(R.id.textview);
  }
 }
}

CursorRowAdapter

Compatible with any RowType implementation, however currently only supports a single ViewType.

CursorRowAdapter<HeaderRow, String> adapter = new CursorRowAdapter<HeaderRow, String>(this, new MockedCursor(20), new CursorMapper<HeaderRow, String>() {
 @Override
 public String map(Cursor c) {
  return String.valueOf(c.getString(1));
 }
 @Override
 public HeaderRow createRow(Context context, String item, int position) {
  return new HeaderRow(item);
 }
}); 
mListView.setAdapter(adapter);

Github Source

The library and sample source code are available here on GitHub.

Categories

Tutorials
comments powered by Disqus

We’re a top UK digital agency - wahoo!

By Sophie Hardbattle

We're Eden Agency - one of the UK's top digital agencies.

Read more

An Introduction to Building a SpriteKit-UIKit Hybrid App

By Alan Chung

A guide to help you get started on making an iOS app that seamlessly combines the visual punch of SpriteKit with the practicality of UIKit.

Read more

How to build a material design prototype using Sketch and Pixate - Part Three

By Mike Scamell

Part three of a three-part tutorial on building a material design prototype. This section focuses on adding more detail to the prototype in Pixate.

Read more

We're Hiring - Web Developer Role

By Craig Gilchrist

We are currently seeking a full time full-stack web developer to join the team at our Knaresborough office.

Read more

How to build a material design prototype using Sketch and Pixate - Part Two

By Mike Scamell

Part two of a three-part tutorial on building a material design prototype. This section focuses on creating a interactive login screen in Pixate.

Read more