how to get value of user id on firebaseRecyclerAdapter - android

my database:
I want to retrieve user id from firebase database. How can I do that?
my code is :
///////////// Recycler Firebase /////////////
firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Post, PostViewHolder>(
Post.class,
R.layout.post_row,
PostViewHolder.class,
dbpostShow
) {
#Override
protected void populateViewHolder(final PostViewHolder viewHolder, Post model, int position) {
String listPostKey = getRef(position).getKey();
viewHolder.setTextPost(model.getText_post());
viewHolder.setHospitalName(model.getHospital_name());
viewHolder.setFullNameUserPoster(model.getPoster_name());
viewHolder.setAgeUserPoster(model.getPoster_age());
String lastSeenAgo = GetTimeAgo.getTimeAgo(model.getTime_post_ago(), getContext());
viewHolder.setTimePostAgo(lastSeenAgo);
viewHolder.setTypeBloodneedPoster(model.getPoster_type_blood());
Toast.makeText(getActivity(), model.getPoster_type_blood(), Toast.LENGTH_SHORT).show();
}
};
recyclerView.setAdapter(firebaseRecyclerAdapter);

If you have created the variable userId in Post class and use getter to get the value.
Otherwise you can use addListenerForSingleValueEvent to get the value:
here is the example how to use it.
firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Post, PostViewHolder>(
Post.class,
R.layout.post_row,
PostViewHolder.class,
dbpostShow
) {
#Override
protected void populateViewHolder(final PostViewHolder viewHolder, Post model, int position) {
String listPostKey = getRef(position).getKey();
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("Post").child("country").child("city").child(listPostKey).child("userId");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String userID = String.valueOf(dataSnapshot.getValue());
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
};
recyclerView.setAdapter(firebaseRecyclerAdapter);

you cant track value when your user id is added on the following code below , and make sure your parent position is correct
yourRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
})

Related

how can i order recyclerview items in firebase by replay timestamps

how can I order my recyclerview items like this
mDatabaseReference = FirebaseDatabase.getInstance().getReference();
productQuery = mDatabaseReference.child("Blog").orderByChild("replaydate");
"replaydate" is located in Replay>psotkey>replaydate I want order blog items by repaydate, is this possiple?
If you want to get the messages by timestamp order you can use
database.orderByChild("replydate").limitToLast(10)
.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
if (dataSnapshot.getValue() != null) {
Model newModel = dataSnapshot.getValue(Model.class);
//Model is you model which you are using for showing data in recyclerview
arraylist.add(newModel);
adapter.notifyDatasetChanged();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});

How can I retrieve all users from firebase database without getting current user?

Im using Recycler view to retrieve all users from firebase like below
#Override
public void onViewCreated(final View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
databaseReference = FirebaseDatabase.getInstance().getReference().child("users");
firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<AllUsers, AllUsersViewHolder>
(AllUsers.class, R.layout.all_users_display_layout, AllUsersViewHolder.class, databaseReference) {
#Override
protected void populateViewHolder(AllUsersViewHolder viewHolder, AllUsers model, final int position) {
viewHolder.setName(model.getName());
viewHolder.view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String visit_user_id = getRef(position).getKey();
Intent intent = new Intent(getActivity(), UserProfilesActivity.class);
intent.putExtra("visit_user_id", visit_user_id);
startActivity(intent);
}
});
}
};
all_user_list.setAdapter(firebaseRecyclerAdapter);
}
public static class AllUsersViewHolder extends RecyclerView.ViewHolder {
View view;
public AllUsersViewHolder(View itemView) {
super(itemView);
view = itemView;
}
public void setName(String name) {
TextView all_user_name = (TextView) view.findViewById(R.id.all_user_name);
all_user_name.setText(name);
}
}
How can I retrieve users without the current users becasuse Im using
this list to add friend scenario
and my database structure like below
users
key
name:xxxx
key
name:yyyy
please help me im new to these stuff
Its a list so:
databaseReference.orderByChild("id").equalTo(null).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
String name=dataSnapshot.child("name").getValue().toString();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Use ChildEventListener for lists it will iterate through the names inside the node users
So you can do this:
users
key
name:xxxx
id:true
key
name:yyyy

Firebase RecyclerView Adapter - Join Query

I am trying to get UserID from one table(homeaccount) and get the user's info from another table(userinfo) using the user id. I tried to do it by the following way. But, it is overwriting the cardviews one on top of another.
databaseReference.child("homeaccount/"+globalSharedPrefs.getUserDetail("currenthome")+"/Users")
.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
String str_iteration_uid = dataSnapshot.getKey();
userQuery = databaseReference.child("userinfo").orderByChild("uid").equalTo(str_iteration_uid);
firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<HomeUsers, HomeUsersViewHolder>(
HomeUsers.class,
R.layout.cardview_manage_user,
HomeUsersViewHolder.class,
userQuery
){
#Override
protected void populateViewHolder(final HomeUsersViewHolder viewHolder, final HomeUsers model, int position) {
//viewHolder.setFirstName(model.getFirstName());
//viewHolder.setProfilePicture(model.getProfilePicture());
}
};
recyclerView.setAdapter(firebaseRecyclerAdapter);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});

How to know number of items returned by query in Firebase

I have this query in my Firebase
mDataBase = FirebaseDatabase.getInstance().getReference("animals);
query = mDataBase.orderByChild("height").limitToLast(20);
query.addChildEventListener(new AnimalsEventListener());
My listener
private class AnimalsEventListener implements ChildEventListener{
private AnimalsEventListener(){
}
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Animals details = dataSnapshot.getValue(Animals.class);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
}
How can I get the size of all animals that matched the query before working on dataSnapShot? sometimes they can be less than 20;
It's not possible to know children count using ChildEventListener, use ValueEventListener instead.
public class AnimalsEventListener implements ValueEventListener {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.getChildrenCount() == 20) {
for (DataSnapshot dataSnapshotEntry : dataSnapshot.getChildren()) {
Animals details = dataSnapshotEntry.getValue(Animals.class);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
}
To attach this listener, use addValueEventListener() method
query.addValueEventListener(new AnimalsEventListener());
If you wanna use childEventListener i recommend u to use official FirebaseArray class.
To get the item count:
FirebaseArray mFirebaseArray = FirebaseArray(Query ref);
mFirebaseArray.getCount();

Firebase android pagination

I'm building an app which will show videos stored on firebase. The list of videos needs to be paginated fetching most recent 20 videos at a time.
Here is the code I thought would work
private void getVideos() {
Query videosQuery = FirebaseUtil.getVideosRef();
videosQuery.startAt(0);
videosQuery.endAt(1);
ChildEventListener videosChildEventListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
String date = dataSnapshot.getKey();
String temp = date;
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d(tag, "database error");
}
};
ValueEventListener videoValueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String date = dataSnapshot.getKey();
String temp = date;
long count = dataSnapshot.getChildrenCount();
String value = dataSnapshot.getValue().toString();
temp = value;
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d(tag, "database error");
}
};
// videosQuery.addChildEventListener(videosChildEventListener);
videosQuery.addValueEventListener(videoValueEventListener);
}
But above code retrieves entire list of videos instead of limited videos. How can pagination be implemented.
Below is the code I'm using for pagination which shows the latest node first.
public void getImages() {
Query imagesQuery = FirebaseDatabase.getInstance().getReference().child("englishDps").child(mChildName).orderByKey().limitToLast(21);
ChildEventListener childEventListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Image image = dataSnapshot.getValue(Image.class);
image.setNodeKey(dataSnapshot.getKey());
mTempImages.add(image);
if (mTempImages.size() == 21) {
mLastKey = mTempImages.get(0).getNodeKey();
Collections.reverse(mTempImages);
mTempImages.remove(mTempImages.size() - 1);
mImages.addAll(mTempImages);
setAdapter();
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
if (isAdded()) {
Toast.makeText(getActivity(), "Problem loading more images...", Toast.LENGTH_LONG).show();
}
}
};
imagesQuery.addChildEventListener(childEventListener);
}
#Override
public void getMoreImages() {
if (!mGettingMoreImages) {
mGettingMoreImages = true;
Query imagesQuery = FirebaseDatabase.getInstance().getReference("englishDps").child(mChildName).orderByKey().endAt(mLastKey).limitToLast(21);
ChildEventListener childEventListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Image image = dataSnapshot.getValue(Image.class);
image.setNodeKey(dataSnapshot.getKey());
mMoreImages.add(image);
if (mMoreImages.size() == 21) {
mLastKey = mMoreImages.get(0).getNodeKey();
Collections.reverse(mMoreImages);
mMoreImages.remove(mMoreImages.size() - 1);
mImages.addAll(mMoreImages);
mMoreImages.clear();
mGettingMoreImages = false;
mImagesAdapter.notifyDataSetChanged();
return;
}
if (mLastKey.equalsIgnoreCase(image.getNodeKey())) {
Collections.reverse(mMoreImages);
mImages.addAll(mMoreImages);
mMoreImages.clear();
mGettingMoreImages = false;
mImagesAdapter.onNoMoreImages();
;
mImagesAdapter.notifyDataSetChanged();
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
if (isAdded()) {
Toast.makeText(getActivity(), "Problem loading more images...", Toast.LENGTH_LONG).show();
}
}
};
imagesQuery.addChildEventListener(childEventListener);
}
}
I have following method to paginate through a firebase realtime database node:
private void getUsers(String nodeId) {
Query query;
if (nodeId == null)
query = FirebaseDatabase.getInstance().getReference()
.child(Consts.FIREBASE_DATABASE_LOCATION_USERS)
.orderByKey()
.limitToFirst(mPostsPerPage);
else
query = FirebaseDatabase.getInstance().getReference()
.child(Consts.FIREBASE_DATABASE_LOCATION_USERS)
.orderByKey()
.startAt(nodeId)
.limitToFirst(mPostsPerPage);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
UserModel user;
List<UserModel> userModels = new ArrayList<>();
for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
userModels.add(userSnapshot.getValue(UserModel.class));
}
mAdapter.addAll(userModels);
mIsLoading = false;
}
#Override
public void onCancelled(DatabaseError databaseError) {
mIsLoading = false;
}
});
}
Every time I reach the bottom of the paginated data, I call the getUsers(mAdapter.getLastItemId()); and then it brings the next set of records.
I have written a complete guide with open source sample app on this that you can check at https://blog.shajeelafzal.com/2017/12/13/firebase-realtime-database-pagination-guide-using-recyclerview/
You want to be using the limitToFirst/limitToLast methods to retrieve a limited number of results.
videosQuery.orderByKey().limitToFirst(20)
https://www.firebase.com/docs/web/api/query/limittofirst.html
You should really consider changing the naming convention of your videos to include leading 0s (i.e. video01, video02... video10, video11) because the above code will display them exactly as you have them above (which I assume is out of order?)
Alternatively, if you're adding the videos via Java, you could just let firebase create the uniqueids via push(). The uniqueid are generated in a way that they'll sort chronilogically, which sounds like it'll suit your need to grab the most recent(ly added?) videos.
https://www.firebase.com/docs/web/api/firebase/push.html
mPageEndOffset = 0;
mPageLimit = 10;
mPageEndOffset += mPageLimit;
deviceListQuery = mDatabase.child("users")
.orderByChild("id").limitToFirst(mPageLimit).startAt(mPageEndOffset);
deviceListQuery.addValueEventListener(YourActivity.this);
You can achieve it by using Firebase database paging library as below code...
In this code, I have shown Post as an data model item and PostViewHolder as ViewHolder
//Initialize RecyclerView
mRecyclerView = findViewById(R.id.recycler_view);
mRecyclerView.setHasFixedSize(true);
LinearLayoutManager mManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mManager);
//Initialize Database
mDatabase = FirebaseDatabase.getInstance().getReference().child("posts");
//Initialize PagedList Configuration
PagedList.Config config = new PagedList.Config.Builder()
.setEnablePlaceholders(false)
.setPrefetchDistance(5)
.setPageSize(10)
.build();
//Initialize FirebasePagingOptions
DatabasePagingOptions<Post> options = new DatabasePagingOptions.Builder<Post>()
.setLifecycleOwner(this)
.setQuery(mDatabase, config, Post.class)
.build();
//Initialize Adapter
mAdapter = new FirebaseRecyclerPagingAdapter<Post, PostViewHolder>(options) {
#NonNull
#Override
public PostViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new PostViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, parent, false));
}
#Override
protected void onBindViewHolder(#NonNull PostViewHolder holder,
int position,
#NonNull Post model) {
holder.setItem(model);
}
#Override
protected void onLoadingStateChanged(#NonNull LoadingState state) {
switch (state) {
case LOADING_INITIAL:
case LOADING_MORE:
// Do your loading animation
mSwipeRefreshLayout.setRefreshing(true);
break;
case LOADED:
// Stop Animation
mSwipeRefreshLayout.setRefreshing(false);
break;
case FINISHED:
//Reached end of Data set
mSwipeRefreshLayout.setRefreshing(false);
break;
case ERROR:
retry();
break;
}
}
#Override
protected void onError(#NonNull DatabaseError databaseError) {
super.onError(databaseError);
mSwipeRefreshLayout.setRefreshing(false);
databaseError.toException().printStackTrace();
}
};
//Set Adapter to RecyclerView
mRecyclerView.setAdapter(mAdapter);
Just visit this below URL for reference
https://firebaseopensource.com/projects/patilshreyas/firebaserecyclerpagination/app/readme.md/
Here you will find implementation of library which helps to implement Pagination of firebase data in RecyclerView
I hope this will help you!
This is how I implemented pagination from firebase database. Consider a case if we have 100 messages. So I first load last 20 messages from firebase i.e. 81 to 100. Then on scroll up I call getMoreMessages() function to load next 20 messages which are 61 to 80 and so on.
public class ChatActivity extends Activity {
String chat_id = "";
long mTotalChildren = 0;
boolean loading = false;
ChildEventListener childEventListenerMain, childEventListenerPager;
ChatActivity mContext = ChatActivity.this;
MessageAdapter messageAdapter;
#BindView(R.id.pb_messages)
ProgressBar pb_messages;
#BindView(R.id.ll_audio)
LinearLayout llAudio;
#BindView(R.id.tv_record_time)
AppCompatTextView tvRecordTime;
#BindView(R.id.tv_cancel)
AppCompatTextView tvCancel;
#BindView(R.id.iv_send)
AppCompatImageView ivSend;
#BindView(R.id.iv_record)
AppCompatImageView ivRecord;
#BindView(R.id.ab_layout)
AppBarLayout abLayout;
#BindView(R.id.messages)
RecyclerView rvMessages;
#BindView(R.id.iv_chat_icon)
SimpleDraweeView ivChatIcon;
#BindView(R.id.iv_camera)
AppCompatImageView ivCamera;
#BindView(R.id.iv_gallery)
AppCompatImageView ivGallery;
#BindView(R.id.message_input)
AppCompatEditText messageInput;
#BindView(R.id.tv_send)
AppCompatTextView tvSend;
#BindView(R.id.toolbar_title)
AppCompatTextView toolbarTitle;
#BindView(R.id.toolbar_status)
AppCompatTextView toolbarStatus;
#BindView(R.id.ll_send)
LinearLayout llSend;
int categoryId, senderId, receiverId, offerId;
String mLastKey;
LinearLayoutManager layoutManager;
private ArrayList<MessageModel> messageArrayList = new ArrayList<>();
private ArrayList<MessageModel> tempMessageArrayList = new ArrayList<>();
#Override
public int getLayoutId() {
return R.layout.activity_chat;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
messageAdapter = new MessageAdapter(mContext, messageArrayList) {
};
layoutManager = new LinearLayoutManager(mContext);
rvMessages.setLayoutManager(layoutManager);
rvMessages.setItemAnimator(new DefaultItemAnimator());
rvMessages.setAdapter(messageAdapter);
rvMessages.setHasFixedSize(true);
rvMessages.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
if (messageArrayList.size() >= 20 &&
!loading && layoutManager.findFirstVisibleItemPosition() == 0 && messageArrayList.size() < mTotalChildren) {
loading = true;
getMoreMessages();
}
}
});
messageAdapter.notifyDataSetChanged();
//used to scroll up recyclerview when keyboard pops up
rvMessages.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
#Override
public void onLayoutChange(View view, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom) {
if (bottom < oldBottom) {
rvMessages.postDelayed(new Runnable() {
#Override
public void run() {
rvMessages.scrollToPosition(messageArrayList.size() - 1);
}
}, 100);
}
}
});
loading = true;
getMessages();
}
public void getMessages() {
FirebaseDatabase.getInstance().getReference().child(pathtomsgs).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.e("childrenCount", String.valueOf(+dataSnapshot.getChildrenCount()));
mTotalChildren = dataSnapshot.getChildrenCount();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Query messageQuery = FirebaseDatabase.getInstance().getReference().child(pathtomsgs).limitToLast(20);
childEventListenerMain = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
loading = true;
MessageModel messageModel = dataSnapshot.getValue(MessageModel.class);
if (messageModel != null) {
messageModel.chat_id = chat_id;
messageModel.message_id = dataSnapshot.getKey();
messageArrayList.add(messageModel);
messageAdapter.notifyDataSetChanged();
mLastKey = messageArrayList.get(0).message_id;
rvMessages.scrollToPosition(messageArrayList.size() - 1);
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(mContext, "Problem loading more images...", Toast.LENGTH_LONG).show();
}
};
messageQuery.addChildEventListener(childEventListenerMain);
ValueEventListener messageChildSINGLEValueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
pb_messages.setVisibility(View.GONE);
System.out.println("We're done loading messages " + dataSnapshot.getChildrenCount() + " items");
loading = false;
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
};
messageQuery.addListenerForSingleValueEvent(messageChildSINGLEValueEventListener);
}
public void getMoreMessages() {
tempMessageArrayList.clear();
Query messageQuery = FirebaseDatabase.getInstance().getReference().child(pathtomsgs).orderByKey().endAt(mLastKey).limitToLast(20);
childEventListenerPager = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
loading = true;
MessageModel messageModel = dataSnapshot.getValue(MessageModel.class);
if (messageModel != null) {
messageModel.chat_id = chat_id;
messageModel.message_id = dataSnapshot.getKey();
tempMessageArrayList.add(messageModel);
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(mContext, "Problem loading more images...", Toast.LENGTH_LONG).show();
}
};
messageQuery.addChildEventListener(childEventListenerPager);
ValueEventListener messageChildSINGLEValueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
System.out.println("We're done loading messages " + dataSnapshot.getChildrenCount() + " items");
tempMessageArrayList.remove(tempMessageArrayList.size() - 1);
messageArrayList.addAll(0, tempMessageArrayList);
mLastKey = messageArrayList.get(0).message_id;
messageAdapter.notifyDataSetChanged();
//rvMessages.scrollToPosition(20);
layoutManager.scrollToPositionWithOffset(19, 0);
loading = false;
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
};
messageQuery.addListenerForSingleValueEvent(messageChildSINGLEValueEventListener);
}
#Override
protected void onDestroy() {
FirebaseDatabase.getInstance().getReference().child(pathtomsgs).removeEventListener(childEventListenerPager);
FirebaseDatabase.getInstance().getReference().child(pathtomsgs).removeEventListener(childEventListenerMain);
super.onDestroy();
}
}
Android paging library can be used to implement pagination for data fetched from firebase database. Data is displayed in recycler view and paging component fetches pages in response to user scroll events.
Paging data source calls your firebase DAO object passing query parameters for the page to be displayed and results are passed back to paging component using callback provided to it.
Here is a complete example for reference http://www.zoftino.com/firebase-pagination-using-android-paging-library
accepted answear dos not work when less then the max. itmes (21) in database.
this is my solution build on the accepted answer:
0)set variables
private String lastMessageKey;
private int totalItemCount;
private int lastVisibleItem;
private boolean isLoadingMoreFollowers = false;
private boolean hasMoreItems = true;
private boolean hasShownNoMoreItemsToast = false;
private boolean initialLoad = true;
private final int MAX_LOAD_ITEMS = 11;
private final int VISIBLE_TRESHOLD = 1;
1) set a listener:
private void setMessageListener() {
if (childEventListener == null) {
mmessageArrayList.clear();
final ArrayList<Mmessage> tempMmessages = new ArrayList<>();
query = mDatabaseInstace.getReference().child(chat1).child(F.CHATS).child(F.MESSAGES).orderByKey().limitToLast(MAX_LOAD_ITEMS-1);
childEventListener = new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
Log.d(TAG, "onChildAdded: -----------------> " + dataSnapshot);
Log.d(TAG, "onChildAdded: -----------------> " + s);
tempMmessages.add(dataSnapshot.getValue(Mmessage.class));
preloadMessagePics(tempMmessages);
if (initialLoad) {
lastMessageKey = tempMmessages.get(0).getMessagePushKey();
initialLoad = false;
}
mmessageArrayList.add(tempMmessages.size()-1, tempMmessages.get(0));
messageAdapter.notifyDataSetChanged();
tempMmessages.clear();
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
Log.d(TAG, "onChildChanged: --------------------------------->");
}
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
Log.d(TAG, "onChildRemoved: ---------------------------------->");
}
#Override
public void onChildMoved(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
Log.d(TAG, "onChildMoved: ------------------------------------>");
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, "onCancelled: ------------------------------------->");
}
};
query.addChildEventListener(childEventListener);
}
}
2) set load more listener:
private void setLoadMoreListener(){
setup.RV_messages.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(#NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
totalItemCount = linearLayoutManager.getItemCount();
lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
if (!isLoadingMoreFollowers && totalItemCount <= (lastVisibleItem+VISIBLE_TRESHOLD) && (totalItemCount >= MAX_LOAD_ITEMS-1)){
if (hasMoreItems) {
getMoreMessages();
Toast.makeText(homeActivity, "load more items", Toast.LENGTH_SHORT).show();
}else {
if (!hasShownNoMoreItemsToast) {
Toast.makeText(homeActivity, "has no more items", Toast.LENGTH_SHORT).show();
hasShownNoMoreItemsToast = true;
}
}
}
}
});
}
3) get more items:
private void getMoreMessages(){
final ArrayList<Mmessage> tempMmessages = new ArrayList<>();
isLoadingMoreFollowers = true;
loadMoreQuery = mDatabaseInstace.getReference().child(chat1).child(F.CHATS).child(F.MESSAGES).orderByKey().endAt(lastMessageKey).limitToLast(MAX_LOAD_ITEMS);
loadMoreChildEventListener = new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
tempMmessages.add(dataSnapshot.getValue(Mmessage.class));
preloadMessagePics(tempMmessages);
if (tempMmessages.size() == MAX_LOAD_ITEMS){
lastMessageKey = tempMmessages.get(0).getMessagePushKey();
Collections.reverse(tempMmessages);
tempMmessages.remove(0);
mmessageArrayList.addAll(tempMmessages);
isLoadingMoreFollowers = false;
messageAdapter.notifyDataSetChanged();
tempMmessages.clear();
return;
}
if (lastMessageKey.equalsIgnoreCase(tempMmessages.get(tempMmessages.size()-1).getMessagePushKey())){
Collections.reverse(tempMmessages);
tempMmessages.remove(0);
mmessageArrayList.addAll(tempMmessages);
isLoadingMoreFollowers = false;
hasMoreItems = false;
messageAdapter.notifyDataSetChanged();
tempMmessages.clear();
}
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
};
loadMoreQuery.addChildEventListener(loadMoreChildEventListener);
}
have fun!!
If you want to get list from firebase realtime database descending with pagination you need use smth like this:
Query query = myRef.child("stories").orderByChild("takenAt").endAt(1600957136000L).limitToLast(30);
Full code, two requests
List<Story> storyList = new ArrayList<>();
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference();
//first request will be look like this
Query query = myRef.child("stories").orderByChild("takenAt").endAt(1600957136000L).limitToLast(30);
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Story story = snapshot.getValue(Story.class);
storyList.add(story);
}
}
Collections.reverse(storyList);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Log.e("ptg", "onCancelled: ", error.toException());
}
});
//second request
long lastTakenAtInTheStoryList = storyList.get(storyList.size()-1).getTakenAt();
Query query2 = myRef.child("stories").orderByChild("takenAt").endAt(lastTakenAtInTheStoryList).limitToLast(30);
query2.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Story story = snapshot.getValue(Story.class);
storyList.add(story);
}
}
Collections.reverse(storyList);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Log.e("ptg", "onCancelled: ", error.toException());
}
});
In the past (but no longer) a question regarding implementing Pagination to a query on Firestore was marked as a duplicate of this question I will answer for FireStore here.
Paginate a query on android Firestore
Query query = db.collection("cities")
.orderBy("population")
.limit(25);
Query next = query;
private void loadCities() {
query = next;
query.get()
.addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot documentSnapshots) {
// Get the last visible document
DocumentSnapshot lastVisible =
documentSnapshots.getDocuments()
.get(documentSnapshots.size() -1);
// Construct a new query starting at this document,
// get the next 25 cities.
next = db.collection("cities")
.orderBy("population")
.startAfter(lastVisible)
.limit(25);
}
});
}
Now just call the loadCities() method whenever you need to load more cities.

Categories

Resources