I am using Firebase database + FirebaseUI to load certain data from Firebase to Android, but the data is not shown in recycler View.
However, by logging the getCount(), I can see that "2" is returned, which means there is data present, but not visible in recyclerView.
Here is my Model class:
public SlideshowModel(){
}
public SlideshowModel(String title, String desc, String image, String date) {
this.title = title;
this.desc = desc;
this.image = image;
this.date = date;
}
public String getTitle() {
return title;
}
public String getDesc() {
return desc;
}
public String getImage() {
return image;
}
public String getDate() {
return date;
}
}
Here is my Adapter class:
public class SlideShowAdapter extends FirebaseRecyclerAdapter<SlideshowModel, SlideShowAdapter.ViewHolder> {
public SlideShowAdapter(#NonNull FirebaseRecyclerOptions<SlideshowModel> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull ViewHolder holder, final int position, #NonNull SlideshowModel model) {
Picasso.get().load(R.drawable.notification).fit().centerCrop().placeholder(R.drawable.placeholders).into(holder.image);
holder.title.setText(model.getTitle());
holder.description.setText(model.getDesc());
holder.date.setText(model.getDate());
holder.delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FirebaseDatabase.getInstance().getReference("notifications").child(getRef(position).getKey()).removeValue();
}
});
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.custom_layout_notifications,
parent, false);
return new ViewHolder(view);
}
class ViewHolder extends RecyclerView.ViewHolder {
ImageView image, notif_icon, share_image, download_image, delete;
TextView title, description, date;
public ViewHolder(#NonNull View itemView) {
super(itemView);
image = itemView.findViewById(R.id.notif);
title = itemView.findViewById(R.id.title);
description = itemView.findViewById(R.id.description);
date = itemView.findViewById(R.id.date);
delete = itemView.findViewById(R.id.delete_notif);
Here is my Activity:
List<SlideshowModel> slideshowModelList;
SlideShowAdapter adapter;
ProgressDialog pd;
RecyclerView recycler_view;
AdView adView;
DatabaseReference dbProducts;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_show_notif);
recycler_view = findViewById(R.id.recycler_view);
pd = new ProgressDialog(this);
recycler_view.setHasFixedSize(true);
setTitle("Show Notifications");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
slideshowModelList = new ArrayList<>();
dbProducts = FirebaseDatabase.getInstance().getReference("notifications");
// adView = findViewById(R.id.adView);
// MobileAds.initialize(this,"ca-app-pub-3940256099942544~3347511713");
// AdRequest adRequest = new AdRequest.Builder().build();
// adView.loadAd(adRequest);
if (isNetworkConnected()) {
pd.setMessage("Loading");
pd.setCanceledOnTouchOutside(false);
pd.show();
final DatabaseReference dbProducts = FirebaseDatabase.getInstance().getReference("notifications");
Log.e("path1", dbProducts.toString());
dbProducts.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
//
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
// Toast.makeText(ShowNotifActivity.this, "Child Changed", Toast.LENGTH_SHORT).show();
}
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
dbProducts.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists() || !slideshowModelList.isEmpty()) {
for (DataSnapshot productSnapshot : dataSnapshot.getChildren()) {
SlideshowModel p = productSnapshot.getValue(SlideshowModel.class);
slideshowModelList.add(p);
}
FirebaseRecyclerOptions<SlideshowModel> options =
new FirebaseRecyclerOptions.Builder<SlideshowModel>()
.setQuery(FirebaseDatabase.getInstance().getReference().child("notifications"), SlideshowModel.class)
.build();
adapter = new SlideShowAdapter(options);
recycler_view.setAdapter(adapter);
// adapter = new SlideShowAdapter(SlideshowModel)
String current_counts = String.valueOf(dataSnapshot.getChildrenCount());
Log.e("Curr_Count : ", current_counts);
Collections.reverse(slideshowModelList);
recycler_view.setAdapter(adapter);
// lovelyProgressDialog.dismiss();
pd.dismiss();
}
else {
Toast.makeText(ShowNotifActivity.this, "No Notifications Available", Toast.LENGTH_SHORT).show();
pd.dismiss();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(getApplicationContext(), "Some Error Occured", Toast.LENGTH_SHORT).show();
pd.dismiss();
}
});
} else {
pd.dismiss();
new AlertDialog.Builder(getApplicationContext())
.setTitle("No Internet Available")
.setMessage("Please connect to Internet to get the Notifications")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
}
}).show();
}
final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext());
recycler_view.setLayoutManager(linearLayoutManager); // set LayoutManager to RecyclerView
}
Update
I initialised the Constructors in AdapterClass, but still no luck.
Everytime you set data to your adapter you need to call
notifyDataSetChanged()
To refresh the adapter's data.
Useful link
Related
I am currently using Value Event Listener in my Code to show messages and it does not shows any error but my only problem is when whenever i add a new send or receive a new message my whole list gets updated all the previous messages are called and it uses a lot of memory currently i am taking care of it my clearing recyclerview every time the value event listener is called but now i want to add Child Event Listener in place of value event listener to save memory but whenever i add child event listener my messages are shown multiple times in recyclerview but after i restart the activity there is only one message in recyclerview.
MyCode
MessageActivity.java
public class MessageActivity extends AppCompatActivity {
CircleImageView profile_image;
TextView user_name;
FirebaseFirestore fstore;
FirebaseAuth fAuth;
FirebaseUser fuser;
DatabaseReference reference;
Toolbar toolbar;
ImageButton imageButton;
EditText textsend;
String userID;
MessageAdapter messageAdapter;
List<Chat> mChat;
RecyclerView recyclerView;
String TAG = "MyTag";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_message);
fAuth=FirebaseAuth.getInstance();
fstore=FirebaseFirestore.getInstance();
userID = fAuth.getCurrentUser().getUid();
profile_image=findViewById(R.id.profile_image);
user_name=findViewById(R.id.username);
imageButton=findViewById(R.id.btn_send);
textsend=findViewById(R.id.text_send);
recyclerView=findViewById(R.id.recycler_view2);
recyclerView.setHasFixedSize(true);
LinearLayoutManager linearLayoutManager= new LinearLayoutManager(getApplicationContext());
linearLayoutManager.setStackFromEnd(true);
recyclerView.setLayoutManager(linearLayoutManager);
toolbar=findViewById(R.id.myToolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle("");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
finish();
}
});
Intent intent=getIntent();
fuser=FirebaseAuth.getInstance().getCurrentUser();
String userid=intent.getStringExtra("userid");
String username= intent.getStringExtra("UserName");
reference = FirebaseDatabase.getInstance().getReference("Users").child(userid);
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
User user = dataSnapshot.getValue(User.class);
user_name.setText(user.getFirst());
if (user.getImageURL().equals("default")){
profile_image.setImageResource(R.mipmap.ic_launcher);
} else {
//and this
Glide.with(getApplicationContext()).load(user.getImageURL()).into(profile_image);
}
readMessages(fuser.getUid(), userid, user.getImageURL());
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
imageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String msg=textsend.getText().toString();
textsend.setText("");
if (!msg.equals("")){
sendMessage(fuser.getUid(),userid,msg);
}
else {
Toast.makeText(MessageActivity.this,"Empty messages cant be send",Toast.LENGTH_SHORT).show();
}
}
});
}
private void sendMessage(String sender, final String receiver, String message) {
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("sender", sender);
hashMap.put("receiver", receiver);
hashMap.put("message", message);
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Chats");
String key = reference.push().getKey();
reference.child(key).setValue(hashMap);
}
private void readMessages(String myid,String userid,String imageurl){
mChat=new ArrayList<>();
reference=FirebaseDatabase.getInstance().getReference("Chats");
reference.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
Chat chat= dataSnapshot.getValue(Chat.class);
assert chat!=null;
if (chat.getReceiver().equals(myid) && chat.getSender().equals(userid)||
chat.getReceiver().equals(userid)&&chat.getSender().equals(myid)){
chat.setMessageId(dataSnapshot.getKey());
mChat.add(chat);
Log.d(TAG,"msg "+chat.getMessage());
}
messageAdapter=new MessageAdapter(MessageActivity.this,mChat, imageurl);
recyclerView.setAdapter(messageAdapter);
messageAdapter.notifyDataSetChanged();
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
Chat chat=dataSnapshot.getValue(Chat.class);
chat.setMessageId(dataSnapshot.getKey());
mChat.remove(chat);
messageAdapter.notifyDataSetChanged();
}
#Override
public void onChildMoved(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
/*
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mChat.clear();
for (DataSnapshot snapshot:dataSnapshot.getChildren()) {
Chat chat=snapshot.getValue(Chat.class);
assert chat != null;
if (chat.getReceiver().equals(myid) && chat.getSender().equals(userid)||
chat.getReceiver().equals(userid)&&chat.getSender().equals(myid)){
mChat.add(chat);
Log.d(TAG,"msg "+chat.getMessage());
}
messageAdapter=new MessageAdapter(MessageActivity.this,mChat, imageurl);
recyclerView.setAdapter(messageAdapter);
messageAdapter.notifyDataSetChanged();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
*/
}
}
MessageAdapter.java
public class MessageAdapter extends RecyclerView.Adapter<MessageAdapter.ViewHolder> {
public static final int MSG_TYPE_LEFT = 0;
public static final int MSG_TYPE_RIGHT = 1;
private Context mContext;
private List<Chat> mChat;
String imageurl;
FirebaseUser fuser;
public MessageAdapter(Context mContext, List<Chat> mChat,String imageurl) {
this.mContext = mContext;
this.mChat = mChat;
this.imageurl=imageurl;
}
#NonNull
#Override
public MessageAdapter.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
if (viewType == MSG_TYPE_RIGHT) {
View view = LayoutInflater.from(mContext).inflate(R.layout.chat_item_right, parent, false);
return new MessageAdapter.ViewHolder(view);
}
else {
View view = LayoutInflater.from(mContext).inflate(R.layout.chat_item_left, parent, false);
return new MessageAdapter.ViewHolder(view);
}
}
#Override
public void onBindViewHolder(#NonNull MessageAdapter.ViewHolder holder, int position) {
Chat chat=mChat.get(position);
holder.show_message.setText(chat.getMessage());
if (imageurl.equals("default")){
holder.profile_image.setImageResource(R.mipmap.ic_launcher);
} else {
Glide.with(mContext).load(imageurl).into(holder.profile_image);
}
holder.show_message.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
String message_id=chat.getMessageId();
Task<Void> task = Utils.removeUser(message_id);
task.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Toast.makeText(mContext,"Message Deleted",Toast.LENGTH_SHORT).show();
}
});
return true;
}
});
}
#Override
public int getItemCount() {
return mChat.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
public TextView show_message;
public ImageView profile_image;
public ViewHolder(#NonNull View itemView) {
super(itemView);
show_message=itemView.findViewById(R.id.show_message);
profile_image=itemView.findViewById(R.id.profile_image);
}
}
#Override
public int getItemViewType(int position) {
fuser= FirebaseAuth.getInstance().getCurrentUser();
if (mChat.get(position).getSender().equals(fuser.getUid())){
return MSG_TYPE_RIGHT;
}
else {
return MSG_TYPE_LEFT;
}
}
}
Use below code. Remove ValueEventListener calls. You should add your logic inside onChildAdded
reference.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
Chat chat= dataSnapshot.getValue(Chat.class);
assert chat!=null;
if (chat.getReceiver().equals(myid) && chat.getSender().equals(userid)||
chat.getReceiver().equals(userid)&&chat.getSender().equals(myid)){
mChat.add(chat);
Log.d(TAG,"msg "+chat.getMessage());
}
messageAdapter=new MessageAdapter(MessageActivity.this,mChat, imageurl);
recyclerView.setAdapter(messageAdapter);
messageAdapter.notifyDataSetChanged();
}
#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) {
}
});
I tried so many solutions about this, but none of this resolve my problem. I can not reach the database using recyclerview. I have firebase realtime database data like this;
Tag
--- Main Category
----- keyID
------ main-Category, sub-category
Tags class
public class Tags {
private String id;
private String mainTags;
private String subTags;
public Tags() {}
public Tags(String id, String mainTags, String subTags) {
this.id = id;
this.mainTags = mainTags;
this.subTags = subTags;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getMainTags() {
return mainTags;
}
public void setMainTags(String mainTags) {
this.mainTags = mainTags;
}
public String getSubTags() {
return subTags;
}
public void setSubTags(String subTags) {
this.subTags = subTags;
}
}
and this is TagAdapter
public class TagAdapter extends RecyclerView.Adapter<TagAdapter.ItemViewHolder> {
private List<Tags> mTagList;
private Context mContext;
public TagAdapter(List<Tags> mTagList, Context mContext) {
this.mTagList = mTagList;
this.mContext = mContext;
}
#NonNull
#Override
public ItemViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.each_item_tags, parent,false);
return new ItemViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ItemViewHolder holder, int position) {
Tags tags = mTagList.get(position);
holder.tvTags.setText(tags.getSubTags());
holder.tvMainTags.setText(tags.getMainTags());
}
#Override
public int getItemCount() {
return mTagList.size();
}
public class ItemViewHolder extends RecyclerView.ViewHolder{
private TextView tvMainTags, tvTags;
public ItemViewHolder(#NonNull View itemView) {
super(itemView);
tvMainTags = itemView.findViewById(R.id.tvMainTag);
tvTags = itemView.findViewById(R.id.tvTags);
}
}
}
TagsFragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_tags, container, false);
rvTags = view.findViewById(R.id.rvTags);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
rvTags.setLayoutManager(linearLayoutManager);
rvTags.hasFixedSize();
tagAdapter = new TagAdapter(tagsList, getContext());
rvTags.setAdapter(tagAdapter);
return view;
}
private void getTagView(){
FirebaseDatabase firebaseDatabase = FirebaseDatabase.getInstance();
DatabaseReference dbRefTags = firebaseDatabase.getReference().child("Tag");
dbRefTags.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
for (DataSnapshot ds : dataSnapshot.getChildren()){
if (ds.exists()) {
try {
Tags tags = ds.getValue(Tags.class);
tagsList.add(tags);
}catch (Exception e){
Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_LONG).show();
}
}else {
Toast.makeText(getContext(), "Bir hata oluştu", Toast.LENGTH_SHORT).show();
}
}
tagAdapter.notifyDataSetChanged();
}
#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) {
}
});
}
There is no error show up when running but i couldn't be able to retrieve data. And i tried firebaseRecyclerView.Adapter also and in the last dependency, i couldn't make it work. I don't know what is wrong in here. how can i solve this?
Get The data with child name ds.child("SubTag").getValue()
dbRefTags.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot parentDS : dataSnapshot.getChildren()) {
Log.d("Tag:", String.valueOf(parentDS.getKey()));
for (DataSnapshot ds : parentDS.getChildren()) {
Tags tags = new Tags();
tags.setMainTag(parentDS.getKey());
tags.setSubTag(ds.child("SubTag").getValue().toString());
Log.d("Tag: -> SubTag)", tags.getSubTag());
tagsList.add(tags);
}
}
tagAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Toast.makeText(getContext(), databaseError.getMessage(), Toast.LENGTH_SHORT).show();
}
});
I want to hide the current user in RequestsFragment in recyclerview. I tried to setVisibility feature. The current user's informantions are not seen to him. But there is a space still in recyclerview. How can i also delete space between other items. I mean if I have sent a request to other users I dont want to see myself at requests fragment.
public class RequestsFragment extends Fragment {
private RecyclerView recyclerView_friendRequestsList;
private View mainView;
private DatabaseReference friendRequestsDatabaseReference;
private DatabaseReference usersDatabaseReference;
private FirebaseAuth firebaseAuth;
private String current_user_id;
public RequestsFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
mainView = inflater.inflate(R.layout.fragment_requests, container, false);
recyclerView_friendRequestsList = mainView.findViewById(R.id.friendRequests_list);
recyclerView_friendRequestsList.setHasFixedSize(true);
recyclerView_friendRequestsList.setLayoutManager(new LinearLayoutManager(getContext()));
firebaseAuth = FirebaseAuth.getInstance();
current_user_id = firebaseAuth.getCurrentUser().getUid();
friendRequestsDatabaseReference = FirebaseDatabase.getInstance().getReference().child("Friend Requests");
friendRequestsDatabaseReference.keepSynced(true);
usersDatabaseReference = FirebaseDatabase.getInstance().getReference().child("Users");
usersDatabaseReference.keepSynced(true);
return mainView;
}
#Override
public void onStart() {
super.onStart();
final FirebaseRecyclerAdapter<FriendRequests, RequestsFragment.FriendRequestsViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<FriendRequests, FriendRequestsViewHolder>(
FriendRequests.class,
R.layout.users_single_layout,
RequestsFragment.FriendRequestsViewHolder.class,
friendRequestsDatabaseReference
) {
#Override
protected void populateViewHolder(final FriendRequestsViewHolder viewHolder, FriendRequests model, final int position) {
final String user_id = getRef(position).getKey();
friendRequestsDatabaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.hasChild(user_id)){
usersDatabaseReference.child(user_id).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (!user_id.equals(current_user_id)) {
final String user_displayName = dataSnapshot.child("display_name").getValue().toString();
final String user_thumbImage = dataSnapshot.child("thumb_image").getValue().toString();
if (dataSnapshot.hasChild("online")) {
String userOnline = dataSnapshot.child("online").getValue().toString();
viewHolder.setUserOnline(userOnline);
}
viewHolder.setName(user_displayName);
viewHolder.setImage(user_thumbImage);
viewHolder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent profileIntent = new Intent(getContext(), ProfileActivity.class);
profileIntent.putExtra("user_id", user_id);
startActivity(profileIntent);
}
});
} else {
viewHolder.mView.setVisibility(View.GONE);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
friendRequestsDatabaseReference.child(current_user_id).child(user_id).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChild("request_type")) {
String request_type = dataSnapshot.child("request_type").getValue().toString();
viewHolder.setRequest_type(request_type);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
};
recyclerView_friendRequestsList.setAdapter(firebaseRecyclerAdapter);
}
public static class FriendRequestsViewHolder extends RecyclerView.ViewHolder {
View mView;
public FriendRequestsViewHolder(View itemView) {
super(itemView);
mView = itemView;
}
public void setName(String name) {
TextView userNameView = mView.findViewById(R.id.user_single_displayName);
userNameView.setText(name);
}
public void setRequest_type(String request_type) {
TextView userStatusView = mView.findViewById(R.id.user_single_status);
userStatusView.setText(request_type);
}
public void setImage(final String thumb_image) {
CircleImageView userImageView = mView.findViewById(R.id.user_single_image);
Picasso.get().load(thumb_image).placeholder(R.mipmap.default_avatar).into(userImageView);
}
public void setUserOnline(String online_status) {
ImageView userOnlineView = mView.findViewById(R.id.user_single_online);
if (online_status.equals("true")) {
userOnlineView.setVisibility(View.VISIBLE);
} else {
userOnlineView.setVisibility(View.INVISIBLE);
}
}
}
}
I'm making a chat application with RecyclerView and List class to store messages from Firebase Database and want to scroll at the bottom of the recylcerView when Chat Activity is opened but error is.....Adapter always returns zero while calling adapter.getItemcount() method . All messages are being displayed with no problem.
Custom Adapter java file
public class ChatCustomAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
private FirebaseUser mUser;
private String currentUser;
private List<ChatModel> msgList;
//Constructor
public ChatCustomAdapter(List<ChatModel> msgList) {
this.msgList = msgList;
FirebaseAuth mAuth = FirebaseAuth.getInstance();
mUser = mAuth.getCurrentUser();
currentUser = mUser.getUid();
}
#Override
public int getItemCount() {
return msgList.size();
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v;
if(viewType==0){
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_single__user_item_layout,parent,false);
return new SelfViewHolder(v);
}else if(viewType==1){
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_single_other_user_item_layout,parent,false);
return new OtherViewHolder(v);
}else{
return null;
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
int layout = holder.getItemViewType();
ChatModel model = msgList.get(position);
String msg = model.getMsg();
if(layout==0){
SelfViewHolder sHolder = (SelfViewHolder)holder;
sHolder.setSelfMsgItems(msg);
}else if(layout==1){
OtherViewHolder oHolder = (OtherViewHolder)holder;
oHolder.setOtherMsgItems(msg);
}
}
#Override
public int getItemViewType(int position) {
super.getItemViewType(position);
int layout;
ChatModel model = msgList.get(position);
String from = model.getFrom();
if(from.equals(currentUser)){
layout=0;
}else{
layout=1;
}
return layout;
}
class SelfViewHolder extends RecyclerView.ViewHolder{
TextView msgtxt,timetxt;
SelfViewHolder(View itemView) {
super(itemView);
msgtxt = itemView.findViewById(R.id.chat_sinhle_user_item_textview);
timetxt = itemView.findViewById(R.id.chat_sinhle_user_item_timeview);
}
void setSelfMsgItems(String data){
msgtxt.setText(data);
}
}
class OtherViewHolder extends RecyclerView.ViewHolder{
TextView msgtxt,timetxt;
public OtherViewHolder(View itemView) {
super(itemView);
msgtxt = itemView.findViewById(R.id.chat_other_user_item_textview);
timetxt = itemView.findViewById(R.id.chat_other_user_item_timeview);
}
public void setOtherMsgItems(String data){
msgtxt.setText(data);
}
}
}
Chat Activity java file
protected void onStart() {
super.onStart();
//region RETREIVING MESSAGES FROM SERVER
msgQ = mDatabase.child("messages").child(current_user).child(otherusername).orderByChild("time");
msgQ.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
ChatModel model = dataSnapshot.getValue(ChatModel.class);
mLsit.add(msgposition++, model);
mAdapter.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) {
}
});
//endregion
recyclerView.scrollToPosition(mAdapter.getItemCount()-1);
}
I think getItemCount() returns zero because you call this method outside of ChildEventListener. So you retrieve itemcount when there are no elements in mLsit yet.
The fastest and a little bit dirty solution here is to put scrollToPosition in onChildAdded method. Also, I would modify code this way
protected void onStart() {
super.onStart();
//region RETREIVING MESSAGES FROM SERVER
msgQ = mDatabase.child("messages").child(current_user).child(otherusername).orderByChild("time");
msgQ.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
ChatModel model = dataSnapshot.getValue(ChatModel.class);
mLsit.add(msgposition, model);
mAdapter.notifyItemInserted(msgposition)
recyclerView.scrollToPosition(msgposition);
msgposition++;
}
#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) {
}
});
//endregion
}
I have some data in firebase which gets changed on some specific actions and I want that change to be shown in the app.
I have a RecyclerView in which all the data from firebase is getting populated.
Here's code:
databaseReference.child("uListings").child(AccessToken.getCurrentAccessToken().getUserId()).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
// recyclerview gets populated here
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
if (dataSnapshot.getValue() != null) {
Map<String,String> map = (Map<String,String>)dataSnapshot.getValue();
Map<ArrayList<String>,ArrayList<String>> map2 = (Map<ArrayList<String>,ArrayList<String>>)dataSnapshot.getValue();
String pDescription = map.get("pDescription");
String pDuration = map.get("pDuration");
String pPrice = map.get("pPrice");
String postedAt = map.get("postedAt");
String views = map.get("views");
ArrayList<String> imageUrl = map2.get("imageUrl");
if (imageUrl != null) {
UHandler pHandler = new UHandler(imageUrl.get(0), pDescription, pDuration, pPrice, postedAt, views);
list.add(pHandler);
adapter.notifyDataSetChanged();
progressBar.setVisibility(View.INVISIBLE);
} else {
Toast.makeText(getBaseContext(), "imageUrlNone", Toast.LENGTH_SHORT).show();
}
} else {
Log.d("PDPchange", "NULL");
progressBar.setVisibility(View.INVISIBLE);
}
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Here's UHandlerAdapter.java:
public class UHandlerAdapter extends RecyclerView.Adapter<UHandlerAdapter.MyViewHolder> {
private Context mContext;
private List<UHandler> listingList;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView pDescription, pDuration, pPrice, postedAt, listingViews, imageUrl;
public ArrayList<String> imageUrls;
public CircleImageView pImage;
public MyViewHolder(View view) {
super(view);
pImage = (CircleImageView) view.findViewById(R.id.p_image_profile);
pDescription = (TextView) view.findViewById(R.id.p_description_profile);
pDuration = (TextView) view.findViewById(R.id.p_duration_profile);
pPrice = (TextView) view.findViewById(R.id.p_price_profile);
postedAt = (TextView) view.findViewById(R.id.p_posted_when_profile);
listingViews = (TextView) view.findViewById(R.id.listing_views_profile);
imageUrl = (TextView) view.findViewById(R.id.image_urls_profile);
}
}
public UHandlerAdapter(Context mContext, List<UProfileHandler> listingList) {
this.mContext = mContext;
this.listingList = listingList;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.profile_all, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
UHandler handler = listingList.get(position);
holder.pDescription.setText(handler.getPDescriptionProfile());
holder.pDuration.setText(handler.getPDurationProfile());
holder.pPrice.setText(handler.getPPriceProfile());
holder.postedAt.setText(handler.getPostedAt());
holder.listingViews.setText(handler.getListingViews());
// loading album cover using Glide library
Glide.with(mContext)
.load(handler.getPImageProfile())
.apply(new RequestOptions().placeholder(R.drawable.ic_placeholder).error(R.drawable.ic_error))
.into(holder.pImage);
}
#Override
public int getItemCount() {
return listingList.size();
}
}
The problem is that in onChildChanged() the views which gets changed add a complete other item in the list reflecting it's changed value and not just gets updated in previously added items in onChildAdded().
How can I just update it in the previously added items itself?
You can store keys in order to update it e.g:
ArrayList<String> mKeys = new ArrayList<String>();
databaseReference.child("uListings").child(AccessToken.getCurrentAccessToken().getUserId()).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
// recyclerview gets populated here
String key = dataSnapshot.getKey();
mKeys.add(key);
adapter.notifyDataSetChanged();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
if (dataSnapshot.getValue() != null) {
.......
//now we get the index to update specific value
String key = dataSnapshot.getKey();
int index = mKeys.indexOf(key);
list.set(index, pHandler);
adapter.notifyDataSetChanged();
....
}