Skip to content

Instantly share code, notes, and snippets.

@chanakin
Created August 26, 2015 19:27
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save chanakin/ecefae62053af5f3e2b5 to your computer and use it in GitHub Desktop.
Save chanakin/ecefae62053af5f3e2b5 to your computer and use it in GitHub Desktop.
This adapter wraps multiple adapters with different object types for use with a recyclerview.
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.ViewGroup;
/**
* Created by Chantell Osejo on 8/7/15.
* This adapter wraps multiple adapters with different object types for use with a recyclerview.
* Copyright (C) 2015 Chantell Osejo
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
public class MultiObjectAdapterRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private RecyclerView.Adapter[] containedAdapters;
// In onCreateViewHolder, we are only given view type. This does not map well if,
// as is the case for this adapter, multiple adapters are involved, since adapters' view types
// are not guaranteed to be unique (one adapter could use the same "viewType" int as another).
// This means that we can't just return the view type specified by the adapter that coordinates with the position in question,
// but we also can't return the index of the adapter, either (because this means the actual view type would be lost, although
// we could then retrieve the adapter in onCreateViewHolder using the viewType as the index in our list of containedAdapters).
// So this object, AdapterItemViewType, is simply a container object that pairs an adapter with a view type.
// This object is then added to this SparseArray, which guarantees it has a unique key, which will become the "viewType"
// we receive in onCreateViewHolder. We'll use that key to retrieve the AdapterItemViewType object, which will then point
// to both the adapter and the actual viewType we care about.
private SparseArray<AdapterItemViewType> adapterItemViewTypes = new SparseArray<>();
class AdapterItemViewType {
public RecyclerView.Adapter adapter;
public int adapterViewType;
public AdapterItemViewType(RecyclerView.Adapter adapter, int viewType) {
this.adapter = adapter;
this.adapterViewType = viewType;
}
}
public MultiObjectAdapterRecyclerViewAdapter(RecyclerView.Adapter[] adapterList) {
containedAdapters = adapterList;
for (RecyclerView.Adapter adapter : containedAdapters) {
adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override
public void onChanged() {
notifyDataSetChanged();
}
});
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
AdapterItemViewType adapterItemViewType = adapterItemViewTypes.get(viewType);
return adapterItemViewType.adapter.onCreateViewHolder(parent, adapterItemViewType.adapterViewType);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
//Figure out the right adapter that this should be handled by
getAdapterForPosition(position).onBindViewHolder(holder, getRelativePositionInAdapter(position));
}
public RecyclerView.Adapter getAdapterForPosition(int position) {
for (RecyclerView.Adapter adapter : containedAdapters) {
if (adapter.getItemCount() > position) {
return adapter;
}
position -= adapter.getItemCount();
}
throw new ArrayIndexOutOfBoundsException(position);
}
private int getRelativePositionInAdapter(int position) {
for (int i = 0; i < containedAdapters.length; i++) {
RecyclerView.Adapter adapter = containedAdapters[i];
if (adapter.getItemCount() > position) {
return position;
}
position -= adapter.getItemCount();
}
throw new ArrayIndexOutOfBoundsException(position);
}
@Override
public int getItemViewType(int position) {
RecyclerView.Adapter adapter = getAdapterForPosition(position);
AdapterItemViewType adapterItemViewType = new AdapterItemViewType(adapter, adapter.getItemViewType(getRelativePositionInAdapter(position)));
if (adapterItemViewTypes.size() > position && adapterItemViewTypes.get(position) != null) {
adapterItemViewTypes.put(position, adapterItemViewType);
} else {
adapterItemViewTypes.put(position, adapterItemViewType);
}
return position;
}
@Override
public int getItemCount() {
int count = 0;
for (RecyclerView.Adapter adapter : containedAdapters) {
count += adapter.getItemCount();
}
return count;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment