diff --git a/app/app.iml b/app/app.iml index 860882d15..eaee690ac 100644 --- a/app/app.iml +++ b/app/app.iml @@ -98,8 +98,8 @@ - + diff --git a/app/src/main/java/com/firebase/uidemo/RecyclerViewDemoActivity.java b/app/src/main/java/com/firebase/uidemo/RecyclerViewDemoActivity.java index 23d08fdfc..407ab1744 100644 --- a/app/src/main/java/com/firebase/uidemo/RecyclerViewDemoActivity.java +++ b/app/src/main/java/com/firebase/uidemo/RecyclerViewDemoActivity.java @@ -1,12 +1,10 @@ package com.firebase.uidemo; -import android.app.Activity; import android.graphics.Color; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; -import android.util.Log; import android.view.Gravity; import android.view.View; import android.widget.Button; @@ -18,19 +16,27 @@ public class RecyclerViewDemoActivity extends AppCompatActivity { + + private static final int INITIAL_LOAD_COUNT = 15; + private static final int INCREMENTAL_LOAD_COUNT = 15; + private static final int PREFETCH_THRESHOLD = 5; + + private int mLastLimitCount; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.recycler_view_demo); - final Firebase ref = new Firebase("https://nanochat.firebaseio.com"); + final Firebase ref = new Firebase("https://firebaseui.firebaseio.com/largechat"); final String name = "Android User"; final Button sendButton = (Button) findViewById(R.id.sendButton); final EditText messageEdit = (EditText) findViewById(R.id.messageEdit); final RecyclerView messages = (RecyclerView) findViewById(R.id.messagesList); + final LinearLayoutManager layoutManager = new LinearLayoutManager(this); messages.setHasFixedSize(true); - messages.setLayoutManager(new LinearLayoutManager(this)); + messages.setLayoutManager(layoutManager); sendButton.setOnClickListener(new View.OnClickListener() { @Override @@ -41,50 +47,69 @@ public void onClick(View v) { } }); - FirebaseRecyclerViewAdapter adapter = new FirebaseRecyclerViewAdapter(Chat.class, android.R.layout.two_line_list_item, ChatHolder.class, ref) { + mLastLimitCount = INITIAL_LOAD_COUNT; + final FirebaseRecyclerViewAdapter adapter = + new FirebaseRecyclerViewAdapter(Chat.class, + android.R.layout.two_line_list_item, ChatHolder.class, + ref.orderByKey().limitToLast(mLastLimitCount)) { + @Override + public void populateViewHolder(ChatHolder chatView, Chat chat) { + chatView.messageText.setText(chat.getText()); + chatView.messageText.setPadding(10, 0, 10, 0); + chatView.nameText.setText(chat.getName()); + chatView.nameText.setPadding(10, 0, 10, 15); + if (chat.getName().equals(name)) { + chatView.messageText.setGravity(Gravity.END); + chatView.nameText.setGravity(Gravity.END); + chatView.nameText.setTextColor(Color.parseColor("#8BC34A")); + } else { + chatView.nameText.setTextColor(Color.parseColor("#00BCD4")); + } + } + }; + + messages.setAdapter(adapter); + + messages.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override - public void populateViewHolder(ChatHolder chatView, Chat chat) { - chatView.messageText.setText(chat.getMessage()); - chatView.messageText.setPadding(10, 0, 10, 0); - chatView.nameText.setText(chat.getName()); - chatView.nameText.setPadding(10, 0, 10, 15); - if (chat.getName().equals(name)) { - chatView.messageText.setGravity(Gravity.END); - chatView.nameText.setGravity(Gravity.END); - chatView.nameText.setTextColor(Color.parseColor("#8BC34A")); - } else { - chatView.nameText.setTextColor(Color.parseColor("#00BCD4")); + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + boolean isScrollingUp = dy < 0; + boolean shouldPrefetch = + layoutManager.findFirstVisibleItemPosition() < PREFETCH_THRESHOLD; + + if (isScrollingUp && shouldPrefetch) { + if (shouldPrefetch) { + mLastLimitCount += INCREMENTAL_LOAD_COUNT; + adapter.updateQuery(ref.orderByKey().limitToLast(mLastLimitCount)); + } } } - }; - - messages.setAdapter(adapter); + }); } - - static class Chat { + public static class Chat { String name; - String message; + String text; public Chat() { } - public Chat(String name, String message) { + public Chat(String name, String text) { this.name = name; - this.message = message; + this.text = text; } public String getName() { return name; } - public String getMessage() { - return message; + public String getText() { + return text; } } - static class ChatHolder extends RecyclerView.ViewHolder { + public static class ChatHolder extends RecyclerView.ViewHolder { TextView nameText, messageText; public ChatHolder(View itemView) { diff --git a/library/src/main/java/com/firebase/ui/FirebaseArray.java b/library/src/main/java/com/firebase/ui/FirebaseArray.java index 79fad095c..0473fcb84 100644 --- a/library/src/main/java/com/firebase/ui/FirebaseArray.java +++ b/library/src/main/java/com/firebase/ui/FirebaseArray.java @@ -52,6 +52,12 @@ public FirebaseArray(Query ref) { mQuery.addChildEventListener(this); } + public void updateQuery(Query ref) { + mQuery.removeEventListener(this); + mQuery = ref; + mQuery.addChildEventListener(this); + } + public void cleanup() { mQuery.removeEventListener(this); } @@ -82,6 +88,11 @@ public void onChildAdded(DataSnapshot snapshot, String previousChildKey) { if (previousChildKey != null) { index = getIndexForKey(previousChildKey) + 1; } + if (mSnapshots.size() >= (index + 1) + && mSnapshots.get(index).getKey().equals(snapshot.getKey())) { + return; + } + mSnapshots.add(index, snapshot); notifyChangedListeners(OnChangedListener.EventType.Added, index); } @@ -114,9 +125,11 @@ public void onCancelled(FirebaseError firebaseError) { public void setOnChangedListener(OnChangedListener listener) { mListener = listener; } + protected void notifyChangedListeners(OnChangedListener.EventType type, int index) { notifyChangedListeners(type, index, -1); } + protected void notifyChangedListeners(OnChangedListener.EventType type, int index, int oldIndex) { if (mListener != null) { mListener.onChanged(type, index, oldIndex); diff --git a/library/src/main/java/com/firebase/ui/FirebaseRecyclerViewAdapter.java b/library/src/main/java/com/firebase/ui/FirebaseRecyclerViewAdapter.java index 7df24602a..1f99cf69f 100644 --- a/library/src/main/java/com/firebase/ui/FirebaseRecyclerViewAdapter.java +++ b/library/src/main/java/com/firebase/ui/FirebaseRecyclerViewAdapter.java @@ -29,6 +29,7 @@ package com.firebase.ui; import android.support.v7.widget.RecyclerView; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -133,7 +134,7 @@ public void onChanged(EventType type, int index, int oldIndex) { * combination of limit(), startAt(), and endAt() */ public FirebaseRecyclerViewAdapter(Class modelClass, int modelLayout, Class viewHolderClass, Firebase ref) { - this(modelClass, modelLayout, viewHolderClass, (Query)ref); + this(modelClass, modelLayout, viewHolderClass, (Query) ref); } @@ -180,6 +181,9 @@ public void onBindViewHolder(VH viewHolder, int i) { populateViewHolder(viewHolder, model); } - abstract public void populateViewHolder(VH viewHolder, T model); + public void updateQuery(Query query) { + mSnapshots.updateQuery(query); + } + abstract public void populateViewHolder(VH viewHolder, T model); }