Skip to content

Instantly share code, notes, and snippets.

@achuinard
Created July 13, 2015 02:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save achuinard/ee1a9302d8829e3adb72 to your computer and use it in GitHub Desktop.
Save achuinard/ee1a9302d8829e3adb72 to your computer and use it in GitHub Desktop.
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import com.firebase.client.ChildEventListener;
import com.firebase.client.DataSnapshot;
import com.firebase.client.FirebaseError;
import com.firebase.client.Query;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class FirebaseRecyclerAdapter<T> extends RecyclerView.Adapter {
private static final int VIEW_TYPE_EMPTY_LIST_PLACEHOLDER = 0;
private static final int VIEW_TYPE_OBJECT_VIEW = 1;
protected Query mRef;
protected List<String> mModelKeysList = Collections.synchronizedList(new ArrayList<String>());
protected Map<String, T> mModelKeyMap = Collections.synchronizedMap(new HashMap<String, T>());
private ChildEventListener mListener;
public FirebaseRecyclerAdapter(final Query ref, final Class<T> modelClass) {
mRef = ref;
mModelKeysList = Collections.synchronizedList(new ArrayList<String>());
mModelKeyMap = Collections.synchronizedMap(new HashMap<String, T>());
mListener = mRef.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
final String key = dataSnapshot.getKey();
mModelKeyMap.put(key, dataSnapshot.getValue(modelClass));
int previousIndex = mModelKeysList.indexOf(previousChildName);
int nextIndex = previousIndex + 1;
mModelKeysList.add(nextIndex, key);
notifyDataSetChanged();
}
@Override
public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) {
T newModel = dataSnapshot.getValue(modelClass);
String modelName = dataSnapshot.getKey();
mModelKeyMap.put(modelName, newModel);
notifyDataSetChanged();
}
@Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
final String key = dataSnapshot.getKey();
int index = mModelKeysList.indexOf(key);
mModelKeyMap.remove(key);
mModelKeysList.remove(index);
notifyDataSetChanged();
}
@Override
public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {
String modelName = dataSnapshot.getKey();
mModelKeyMap.put(modelName, dataSnapshot.getValue(modelClass));
int index = mModelKeysList.indexOf(modelName);
mModelKeysList.remove(index);
int previousIndex = mModelKeysList.indexOf(previousChildName);
int nextIndex = previousIndex + 1;
mModelKeysList.add(nextIndex, modelName);
notifyDataSetChanged();
}
@Override
public void onCancelled(FirebaseError firebaseError) {
}
});
}
public void cleanup() {
mRef.removeEventListener(mListener);
mModelKeyMap.clear();
mModelKeysList.clear();
}
@Override
public int getItemCount() {
return mModelKeysList.isEmpty() ? 1 : mModelKeysList.size();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType) {
case VIEW_TYPE_EMPTY_LIST_PLACEHOLDER:
return new EmptyViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.empty_list_item, parent, false));
case VIEW_TYPE_OBJECT_VIEW:
return onCreateViewHolderImpl(parent, viewType);
}
throw new IllegalStateException("Unimplemented viewType");
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (getItemViewType(position)) {
case VIEW_TYPE_EMPTY_LIST_PLACEHOLDER:
((EmptyViewHolder) holder).setEmptyText(getEmptyTextId());
break;
case VIEW_TYPE_OBJECT_VIEW:
onBindViewHolderImpl(holder, position);
break;
}
}
protected abstract int getEmptyTextId();
protected abstract RecyclerView.ViewHolder onCreateViewHolderImpl(ViewGroup parent, int viewType);
protected abstract void onBindViewHolderImpl(RecyclerView.ViewHolder vh, int position);
@Override
public int getItemViewType(int position) {
if (mModelKeysList.isEmpty()) {
return VIEW_TYPE_EMPTY_LIST_PLACEHOLDER;
} else {
return VIEW_TYPE_OBJECT_VIEW;
}
}
}
public class EmptyViewHolder extends RecyclerView.ViewHolder {
@InjectView(R.id.empty_view_holder_text)
TextView mEmptyText;
public EmptyViewHolder(View itemView) {
super(itemView);
ButterKnife.inject(this, itemView);
}
public void setEmptyText(int stringId) {
mEmptyText.setText(stringId);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment