Skip to content

Instantly share code, notes, and snippets.

@AJSer027
Last active July 20, 2018 13:31
Show Gist options
  • Save AJSer027/1fd0e9c19f7560ce7dbb7398e1d330c8 to your computer and use it in GitHub Desktop.
Save AJSer027/1fd0e9c19f7560ce7dbb7398e1d330c8 to your computer and use it in GitHub Desktop.
Firebase paginator from last to first (for chat app)
import android.support.annotation.IntDef;
import android.text.TextUtils;
import com.example.Utils.Pagination.Logger;
import com.google.firebase.database.ChildEventListener;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.Query;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
public class InfiniteFirebaseArray implements ChildEventListener {
private int mCurrentPage = 1;
private String mPrevKey;
private String mLastKey;
public static final int ADDED = 0;
public static final int CHANGED = 1;
public static final int REMOVED = 2;
@IntDef({ADDED, CHANGED, REMOVED})
@Retention(RetentionPolicy.SOURCE)
public @interface EventType {
}
public interface OnChangedListener {
void onChanged(@EventType int type, int index, int oldIndex);
void onCancelled(DatabaseError databaseError);
}
private Query mQuery;
private List<DataSnapshot> mSnapshots = new ArrayList<>();
private int mNumberPerPage;
private int itemPos = 0;
private boolean isDuplicateKey;
private boolean isFirstLoad = true;
private OnChangedListener mListener;
public InfiniteFirebaseArray(Query ref, int numberPerPage) {
mNumberPerPage = numberPerPage;
initQuery(ref);
}
private void initQuery(Query ref) {
Logger.d("NumberPerPage: " + mNumberPerPage);
mQuery = ref.limitToLast(mNumberPerPage * mCurrentPage);
Logger.d("Page (Current)= " + mCurrentPage);
mQuery.addChildEventListener(this);
}
private void initNextQuery(Query ref) {
itemPos = 0;
isFirstLoad = false;
Logger.d("NumberPerPage: " + mNumberPerPage);
Logger.d("IFA (Current)= " + mCurrentPage);
ref.orderByKey().limitToLast(mNumberPerPage).endAt(mLastKey);
ref.addChildEventListener(this);
}
public void cleanup() {
Logger.enter();
mQuery.removeEventListener(this);
Logger.exit();
}
public void more(Query ref) {
if (isHasMore()) {
initNextQuery(ref);
}
}
public int getCount() {
return mSnapshots.size();
}
public DataSnapshot getItem(int index) {
return mSnapshots.get(index);
}
@Override
public void onChildAdded(DataSnapshot snapshot, String previousChildKey) {
if (snapshot == null) {
return;
}
if (isFirstLoad) {
itemPos++;
if (checkDuplicateKey(snapshot.getKey())) {
isDuplicateKey = true;
return;
}
if (itemPos == 1) {
String messageKey = snapshot.getKey();
mLastKey = messageKey;
mPrevKey = messageKey;
}
mSnapshots.add(snapshot);
Logger.d("IFA (itemPos:LastKey)= " + itemPos + " : " + mLastKey);
} else {
String messageKey = snapshot.getKey();
if (checkDuplicateKey(messageKey)) {
isDuplicateKey = true;
return;
}
if (!mPrevKey.equals(messageKey)) {
mSnapshots.add(itemPos++, snapshot);
} else {
mPrevKey = mLastKey;
}
if (itemPos == 1) {
mLastKey = messageKey;
}
Logger.d("IFA (itemPos:LastKey)= " + itemPos + " : " + mLastKey);
}
notifyChangedListeners(ADDED, itemPos);
}
// private boolean checkDuplicateKey(String nextChildKey) {
// if (mSnapshots.size() > 0) {
// DataSnapshot previousSnapshot = mSnapshots.get(mSnapshots.size() - 1);
// String previousChildkey = previousSnapshot == null ? "" : previousSnapshot.getKey();
// return (!TextUtils.isEmpty(previousChildkey) && previousChildkey.equals(nextChildKey));
// }
// return false;
// }
private boolean checkDuplicateKey(String nextChildKey) {
if (mSnapshots.size() > 0) {
for (int i = 0; i < mSnapshots.toArray().length; i++) {
DataSnapshot ds = mSnapshots.get(i);
String key = ds.getKey();
if (key.equals(nextChildKey)) {
return true;
}
}
}
return false;
}
public boolean isHasMore() {
boolean isHasMore = true;
if (isDuplicateKey) {
isHasMore = false;
}
Logger.d("isHasMore: " + isHasMore);
return isHasMore;
}
public void setOnChangedListener(OnChangedListener listener) {
mListener = listener;
}
private void notifyChangedListeners(@EventType int type, int index) {
notifyChangedListeners(type, index, -1);
}
protected void notifyChangedListeners(@EventType int type, int index, int oldIndex) {
if (mListener != null) {
mListener.onChanged(type, index, oldIndex);
}
}
protected void notifyCancelledListeners(DatabaseError databaseError) {
if (mListener != null) {
mListener.onCancelled(databaseError);
}
}
private int getIndexForKey(String key) {
int index = 0;
for (DataSnapshot snapshot : mSnapshots) {
if (snapshot.getKey().equalsIgnoreCase(key)) {
return index;
} else {
index++;
}
}
return -1;
}
@Override
public void onChildChanged(DataSnapshot snapshot, String s) {
int index = getIndexForKey(snapshot.getKey());
if (index != -1) {
mSnapshots.set(index, snapshot);
notifyChangedListeners(CHANGED, index);
}
}
@Override
public void onChildRemoved(DataSnapshot snapshot) {
int index = getIndexForKey(snapshot.getKey());
if (index != -1) {
mSnapshots.remove(index);
notifyChangedListeners(REMOVED, index);
}
}
@Override
public void onChildMoved(DataSnapshot snapshot, String previousChildKey) {
}
@Override
public void onCancelled(DatabaseError databaseError) {
notifyCancelledListeners(databaseError);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment