Back to project page AndroidChat.
The source code is released under:
Copyright 2014 Firebase, https://www.firebase.com/ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ?Software??...
If you think the Android project AndroidChat listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package com.firebase.androidchat; // w ww. ja v a 2 s. co m import android.app.Activity; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; 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.HashMap; import java.util.List; import java.util.Map; /** * @author greg * @since 6/21/13 * * This class is a generic way of backing an Android ListView with a Firebase location. * It handles all of the child events at the given Firebase location. It marshals received data into the given * class type. Extend this class and provide an implementation of <code>populateView</code>, which will be given an * instance of your list item mLayout and an instance your class that holds your data. Simply populate the view however * you like and this class will handle updating the list as the data changes. * * @param <T> The class type to use as a model for the data contained in the children of the given Firebase location */ public abstract class FirebaseListAdapter<T> extends BaseAdapter { private Query mRef; private Class<T> mModelClass; private int mLayout; private LayoutInflater mInflater; private List<T> mModels; private Map<String, T> mModelKeys; private ChildEventListener mListener; /** * @param mRef The Firebase location to watch for data changes. Can also be a slice of a location, using some * combination of <code>limit()</code>, <code>startAt()</code>, and <code>endAt()</code>, * @param mModelClass Firebase will marshall the data at a location into an instance of a class that you provide * @param mLayout This is the mLayout used to represent a single list item. You will be responsible for populating an * instance of the corresponding view with the data from an instance of mModelClass. * @param activity The activity containing the ListView */ public FirebaseListAdapter(Query mRef, Class<T> mModelClass, int mLayout, Activity activity) { this.mRef = mRef; this.mModelClass = mModelClass; this.mLayout = mLayout; mInflater = activity.getLayoutInflater(); mModels = new ArrayList<T>(); mModelKeys = new HashMap<String, T>(); // Look for all child events. We will then map them to our own internal ArrayList, which backs ListView mListener = this.mRef.addChildEventListener(new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) { T model = dataSnapshot.getValue(FirebaseListAdapter.this.mModelClass); mModelKeys.put(dataSnapshot.getKey(), model); // Insert into the correct location, based on previousChildName if (previousChildName == null) { mModels.add(0, model); } else { T previousModel = mModelKeys.get(previousChildName); int previousIndex = mModels.indexOf(previousModel); int nextIndex = previousIndex + 1; if (nextIndex == mModels.size()) { mModels.add(model); } else { mModels.add(nextIndex, model); } } notifyDataSetChanged(); } @Override public void onChildChanged(DataSnapshot dataSnapshot, String s) { // One of the mModels changed. Replace it in our list and name mapping String modelName = dataSnapshot.getKey(); T oldModel = mModelKeys.get(modelName); T newModel = dataSnapshot.getValue(FirebaseListAdapter.this.mModelClass); int index = mModels.indexOf(oldModel); mModels.set(index, newModel); mModelKeys.put(modelName, newModel); notifyDataSetChanged(); } @Override public void onChildRemoved(DataSnapshot dataSnapshot) { // A model was removed from the list. Remove it from our list and the name mapping String modelName = dataSnapshot.getKey(); T oldModel = mModelKeys.get(modelName); mModels.remove(oldModel); mModelKeys.remove(modelName); notifyDataSetChanged(); } @Override public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) { // A model changed position in the list. Update our list accordingly String modelName = dataSnapshot.getKey(); T oldModel = mModelKeys.get(modelName); T newModel = dataSnapshot.getValue(FirebaseListAdapter.this.mModelClass); int index = mModels.indexOf(oldModel); mModels.remove(index); if (previousChildName == null) { mModels.add(0, newModel); } else { T previousModel = mModelKeys.get(previousChildName); int previousIndex = mModels.indexOf(previousModel); int nextIndex = previousIndex + 1; if (nextIndex == mModels.size()) { mModels.add(newModel); } else { mModels.add(nextIndex, newModel); } } notifyDataSetChanged(); } @Override public void onCancelled(FirebaseError firebaseError) { Log.e("FirebaseListAdapter", "Listen was cancelled, no more updates will occur"); } }); } public void cleanup() { // We're being destroyed, let go of our mListener and forget about all of the mModels mRef.removeEventListener(mListener); mModels.clear(); mModelKeys.clear(); } @Override public int getCount() { return mModels.size(); } @Override public Object getItem(int i) { return mModels.get(i); } @Override public long getItemId(int i) { return i; } @Override public View getView(int i, View view, ViewGroup viewGroup) { if (view == null) { view = mInflater.inflate(mLayout, viewGroup, false); } T model = mModels.get(i); // Call out to subclass to marshall this model into the provided view populateView(view, model); return view; } /** * Each time the data at the given Firebase location changes, this method will be called for each item that needs * to be displayed. The arguments correspond to the mLayout and mModelClass given to the constructor of this class. * <p/> * Your implementation should populate the view using the data contained in the model. * * @param v The view to populate * @param model The object containing the data used to populate the view */ protected abstract void populateView(View v, T model); }