Linearlayout manager + recyclerview: StackFromEnd(true) still showing at top instead of bottom - android

I am new to programming in androidstudio/java so I'm looking for some assistance. I'm currently trying to make an app that is similar to facebook messenger by using firebase and android studio. I'm at the stage where I am trying to create the layout for the ChatActivity (see code below). However, I'm having some issues with showing new messages at the bottom of the screen.
I have tried using ".setStackFromEnd(true);" but setting it either true or false, the text still appears at the top! (see images)
Code:
ChatActivity is as follows:
public class ChatActivity extends AppCompatActivity {
//Firebase variables
private FirebaseAuth mAuth;
private DatabaseReference mDatabaseUser, mDatabaseChat;
private FirebaseStorage mStorage;
private StorageReference mStorageReference;
//Recyclerview variables
private RecyclerView recyclerView;
private RecyclerViewChatAdapter mChatAdapter;
//Variables for users
private String userId,friendId,namefriend,chatId;
private CircleImageView mImageFriend;
private ArrayList<ChatObject> resultsChat = new ArrayList<>();
private Button mSendButton;
private EditText mSendText;
private TextView mNameFriend;
//Linear layout manager
private LinearLayoutManager mLayoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
//prevent opening keyboard automatically
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
//Set firebase variables
mAuth = FirebaseAuth.getInstance();
userId = mAuth.getCurrentUser().getUid();
friendId = getIntent().getExtras().getString("friendId");
namefriend = getIntent().getExtras().getString("friendName");
mDatabaseUser = FirebaseDatabase.getInstance().getReference().child("Friends").child(userId).child("Friendlist").child(friendId).child("chatId");
mDatabaseChat = FirebaseDatabase.getInstance().getReference();
mStorage = FirebaseStorage.getInstance();
mStorageReference = mStorage.getReference();
//Get findviewbyId's
recyclerView = (RecyclerView) findViewById(R.id.ChatActivity_recyclerview);
mSendButton = (Button) findViewById(R.id.ChatActivity_Send);
mSendText = (EditText) findViewById(R.id.ChatActivity_SendText);
mNameFriend = (TextView) findViewById(R.id.ChatActivity_Name);
mImageFriend = (CircleImageView) findViewById(R.id.ChatActivity_ImageFriend);
//Filling in recyclerview and adapter
FillInRecyclerView();
//Set name
mNameFriend.setText(" "+namefriend);
//set picture
StorageReference profileRef = mStorageReference.child("profilepictures/"+friendId);
GlideApp.with(this)
.load(profileRef)
.into(mImageFriend);
//Setting database for messages
getChatId();
//Send message
mSendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sendMessage();
}
});
}
private void sendMessage() {
String sendMessageText = mSendText.getText().toString();
if(!sendMessageText.isEmpty()){
DatabaseReference newMessageDb = mDatabaseChat.push();
Map newMessage = new HashMap();
newMessage.put("createdByUser", userId);
newMessage.put("text", sendMessageText);
newMessageDb.setValue(newMessage);
}
mSendText.setText(null);
}
private void getChatId(){
mDatabaseUser.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
chatId = dataSnapshot.getValue().toString();
mDatabaseChat = mDatabaseChat.child("Message").child(chatId);
getChatMessages();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void getChatMessages() {
mDatabaseChat.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
if(dataSnapshot.exists()){
String message = null;
String createdByUser = null;
if (dataSnapshot.child("text").getValue()!=null){
message = dataSnapshot.child("text").getValue().toString();
}
if (dataSnapshot.child("createdByUser").getValue()!=null){
createdByUser = dataSnapshot.child("createdByUser").getValue().toString();
}
if(message!=null && createdByUser!=null){
Boolean currentUserBoolean = false;
if(createdByUser.equals(userId)){
currentUserBoolean=true;
}
ChatObject newMessage = new ChatObject(message, currentUserBoolean, createdByUser);
resultsChat.add(0,newMessage);
mChatAdapter.notifyDataSetChanged();
mLayoutManager.scrollToPositionWithOffset(0,0);
}
}
}
#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) {
}
});
}
public void FillInRecyclerView(){
mLayoutManager = new LinearLayoutManager(this);
recyclerView.setNestedScrollingEnabled(false);
recyclerView.setHasFixedSize(true);
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);
mLayoutManager.scrollToPositionWithOffset(0,0);
mChatAdapter = new RecyclerViewChatAdapter(ChatActivity.this, resultsChat);
recyclerView.setAdapter(mChatAdapter);
recyclerView.setLayoutManager(mLayoutManager);
}
ActivityChat XML:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ChatActivity">
<LinearLayout
android:id="#+id/ChatActivity_LinearLayoutHeader"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#drawable/background_chatheader"
android:paddingStart="7dp"
android:paddingLeft="7dp"
android:windowSoftInputMode="adjustResize"
android:layout_marginBottom="3dp">
<de.hdodenhof.circleimageview.CircleImageView
android:layout_width="45dp"
android:layout_height="45dp"
android:id="#+id/ChatActivity_ImageFriend"
android:src="#mipmap/ic_launcher"
android:layout_gravity="center"
/>
<TextView
android:id="#+id/ChatActivity_Name"
android:layout_width="match_parent"
android:layout_height="60dp"
android:text="Test"
android:gravity="center_vertical|start"
android:textSize="25sp"
android:textColor="#color/white"
android:fontFamily="sans-serif"
/>
</LinearLayout>
<android.support.v4.widget.NestedScrollView
android:layout_below="#+id/ChatActivity_LinearLayoutHeader"
android:layout_above="#id/ChatActivity_LinearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:overScrollMode="never"
android:scrollbarStyle="outsideOverlay"
>
<android.support.v7.widget.RecyclerView
app:stackFromEnd="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#id/ChatActivity_LinearLayout"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
android:id="#+id/ChatActivity_recyclerview"
>
</android.support.v7.widget.RecyclerView>
</android.support.v4.widget.NestedScrollView>
<LinearLayout
android:id="#+id/ChatActivity_LinearLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<EditText
android:layout_weight="0.7"
android:id="#+id/ChatActivity_SendText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="Type your message..."
/>
<Button
android:layout_weight="0.3"
android:id="#+id/ChatActivity_Send"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="send"/>
</LinearLayout>
</RelativeLayout>
Itemlayout xml file for the recyclerview:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/Recyclerview_Parent_Container"
>
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/Recyclerview_ChatImage"
android:layout_width="42dp"
android:layout_height="42dp"
android:src="#mipmap/ic_launcher"
android:visibility="invisible"
/>
<LinearLayout
android:layout_marginStart="9dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="6sp"
android:id="#+id/Recyclerview_Container"
android:orientation="horizontal"
android:background="#drawable/border_chat_bubbles"
android:layout_marginLeft="7dp"
android:layout_marginEnd="7dp">
<TextView
android:id="#+id/Recyclerview_Message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Text"
android:textSize="18sp"
/>
</LinearLayout>
</LinearLayout>
RecyclerView adapter code:
public class RecyclerViewChatAdapter extends RecyclerView.Adapter<RecyclerViewChatAdapter.ViewHolder> {
private List<ChatObject> chatList;
private Context context;
//Firebase
private FirebaseAuth mAuth;
private String CurrentUserId;
private FirebaseStorage mStorage;
private StorageReference mStorageReference;
public RecyclerViewChatAdapter(Context context, List<ChatObject> chatList) {
this.chatList = chatList;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int viewType) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.recyclerview_chatlist_layout, viewGroup, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, final int position) {
//Firebase variables
mStorage = FirebaseStorage.getInstance();
mStorageReference = mStorage.getReference();
mAuth = FirebaseAuth.getInstance();
CurrentUserId = mAuth.getCurrentUser().getUid();
//Setting profile picture into recyclerview
StorageReference profileRef = mStorageReference.child("profilepictures/" + chatList.get(position).getUserid());
GlideApp.with(context)
.load(profileRef)
.into(holder.mProfilepicture);
//Setting message layout for user and friend
holder.mMessage.setText(chatList.get(position).getMessage());
if (chatList.get(position).getCurrentUser()) {
holder.mParentContainer.setGravity(Gravity.END);
holder.mMessage.setTextColor(Color.parseColor("#404040"));
holder.mContainer.setBackgroundResource(R.drawable.border_chat_bubbles);
holder.mProfilepicture.setVisibility(View.INVISIBLE);
} else {
holder.mParentContainer.setGravity(Gravity.START);
holder.mMessage.setTextColor(Color.parseColor("#FFFFFF"));
holder.mContainer.setBackgroundResource(R.drawable.border_chat_bubbles_friend);
holder.mProfilepicture.setVisibility(View.VISIBLE);
//Set picture of friend when multiple messages
int i = 1;
if(position+i<chatList.size()) {
while (!chatList.get(position + i).getCurrentUser()) {
if ((chatList.get(position + i).getCurrentUser()) == chatList.get(position).getCurrentUser()) {
holder.mProfilepicture.setVisibility(View.INVISIBLE);
i++;
} else {
break;
}
if (position + i == chatList.size()) {
break;
}
}
}
}
}
#Override
public int getItemCount() {
return this.chatList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView mMessage;
LinearLayout mContainer, mParentContainer;
CircleImageView mProfilepicture;
public ViewHolder(View itemView) {
super(itemView);
mParentContainer = itemView.findViewById(R.id.Recyclerview_Parent_Container);
mMessage = itemView.findViewById(R.id.Recyclerview_Message);
mContainer = itemView.findViewById(R.id.Recyclerview_Container);
mProfilepicture = itemView.findViewById(R.id.Recyclerview_ChatImage);
}
}
What it looks like on the emulator:
Screenshot of emulator of what it looks like
What I want it to look like:
Emulator of what I want
Now if I set SetStackFromEnd to true or false, I keep getting the same result as in the above picture. However, SetReverseLayout does work! What also does not work is the scrollToPositionWithOffset(0,0); or any other variation, I think the issue must be linked to each other
What have I tried to do already and did not work:
changing the position at what time "FillInRecyclerView()" method is being called, however this did not change anything.
Various combinations of SetReverseLayout/SetStackFromEnd to true
Setting stackfromend to true in the XML code
Changing the RelativeLayout to a LinearLayout in 'ChatActivity.xml'
Setting the relative layout height to match parent
Any help is welcome!
Thank you

You need to use both setStackFromEnd and setReverseLayout. Set both value true and you will get your expected output.
LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(mContext);
recyclerView.setLayoutManager(mLinearLayoutManager);
mLinearLayoutManager.setStackFromEnd(true);
mLinearLayoutManager.setReverseLayout(true);

Related

FATAL EXCEPTION: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference getItemCount

I'm just trying to display all images uploaded to Firebase Storage using a recyclerview. Every time I run my app to test out everything my app crashes and when I check the Logcat it keeps telling me Attempt to invoke interface method 'int java.util.List.size()' on a null object reference at com.myapp.yoody.AdapterOne.getItemCount. I'm just wondering what is the null object its referring to. Is it talking about the fact that it's not connecting to firebase? or what is it? I've been trying for days to get this thing to work and I've got nothing. Please help me out here. I hope my question doesn't sound confusing. Here's my code below. Thanks in advance
//Profilepage (The page where the images are supposed to display)
FirebaseAuth firebaseAuth;
FirebaseUser firebaseUser;
TextView name;
DatabaseReference databaseReference;
StorageReference storageReference;
private Context mccontext=ProfileActivity.this;
RecyclerView recyclerView;
AdapterOne adapter1;
String uid;
// Folder path for Firebase Storage.
ImageView imageView;
//List<ImageUploadInfo> list=new ArrayList<>();
ArrayList<ImageUploadInfo> imagesList;
// Folder path for Firebase Storage.
String Storage_Path = "Images/";
// Root Database Name for Firebase Database.
public static final String Database_Path = "Images";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
recyclerView=findViewById(R.id.recyclerView);
LinearLayoutManager linearLayoutManager=new LinearLayoutManager(this);
recyclerView.setHasFixedSize(true);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
overridePendingTransition(R.anim.slide_right, R.anim.slide_left);
adapter1=new AdapterOne(mccontext,imagesList);
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setAdapter(adapter1);
imagesList=new ArrayList<>();
adapter1.notifyDataSetChanged();
//databaseReference=FirebaseDatabase.getInstance().getReference("Users");
uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
// Assign FirebaseStorage instance to storageReference.
storageReference = FirebaseStorage.getInstance().getReference();
// Assign FirebaseDatabase instance with root database name.
databaseReference = FirebaseDatabase.getInstance().getReference(Database_Path);
// Adding Add Value Event Listener to databaseReference.
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot postSnapshot:dataSnapshot.getChildren() ){
ImageUploadInfo imageUploadInfo=postSnapshot.getValue(ImageUploadInfo.class);
imagesList.add(imageUploadInfo);
}
adapter1 = new AdapterOne(getApplicationContext(), imagesList);
recyclerView.setAdapter(adapter1);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
//My Adapter class
public class AdapterOne extends RecyclerView.Adapter<AdapterOne.ViewHolder> {
Context context;
List<ImageUploadInfo> imagesList;
public AdapterOne(Context c, List<ImageUploadInfo> TempList) {
imagesList = TempList;
context = c;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.cardview, parent, false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
ImageUploadInfo imageUploadInfo = imagesList.get(position);
Glide.with(context).load(imageUploadInfo.getImageUrl()).into(holder.imageView);
}
#Override
public int getItemCount() {
return imagesList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public ImageView imageView;
public ViewHolder(#NonNull View itemView) {
super(itemView);
imageView=(ImageView) itemView.findViewById(R.id.imageview);
}
}
}
//UploadInfo class
public class ImageUploadInfo {
// public String imageName;
public String imageURL;
public ImageUploadInfo() {} // default constructor that takes no arguments
public ImageUploadInfo( String url) {
this.imageURL= url;
}
public String getImageUrl() {
return imageURL;
}
public void setImageURL(String imageURL) {
this.imageURL = imageURL;
}
}
//CardView class
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="horizontal"
android:background="#color/white"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
android:orientation="vertical"
>
<GridLayout
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_marginTop="0dp"
android:alignmentMode="alignMargins"
android:columnCount="1"
android:paddingTop="20dp"
android:columnOrderPreserved="false"
android:rowCount="3">
<!-- 3 -->
<!-- 4 -->
<androidx.cardview.widget.CardView
android:layout_width="350dp"
android:layout_height="320dp"
android:layout_rowWeight="1"
android:layout_columnWeight="1"
android:layout_marginLeft="6dp"
android:layout_marginRight="4dp"
android:layout_marginBottom="10dp"
app:cardCornerRadius="0dp"
app:cardElevation="0dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:id="#+id/imageview"
/>
<!--
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/imagename"
android:text="Image Name"
/>
-->
</androidx.cardview.widget.CardView>
</GridLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
The problem is that you initialize the list AFTER you send it to adapter. So adapter trying to execute its method on the list which is not exist. Move init lane BEFORE send it in adapter

print all users list in android app using firebase

I am working on printing all users based on the UID, but I only get one user printed.
This is the result I am getting now.
Here is what the printingUserList(), this is a small function to retrieve all user information based on UID.
RecyclerView rv;
UserAdapter usrAdapter;
ArrayList<User> mUsrsList;
private void readUsrs(){
LinearLayoutManager LayoutManager = new LinearLayoutManager(this);
rv.setLayoutManager(LayoutManager);
mUsrsList = new ArrayList<>();
final FirebaseUser me = FirebaseAuth.getInstance().getCurrentUser();
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("users");
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
mUsrsList.clear();
for (DataSnapshot ds: dataSnapshot.getChildren()) {
Log.d("TAG_", "A++" + dataSnapshot.getChildrenCount()); //prints 5, which exactly has five users in the database.
User all_usr = ds.getValue(User.class);
if (!all_usr.getUid().equals(me.getUid())) { //won't print itself
mUsrsList.add(all_usr);
}
}
System.out.println(mUsrsList.toString());
usrAdapter = new UserAdapter(RoomUser_Activity.this, mUsrsList);
rv.setAdapter(usrAdapter);
usrAdapter.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) { }
});
}
and this is the recyclerview, should be correct otherwise it prints nothing
public class UserAdapter extends RecyclerView.Adapter<UserAdapter.UserViewHolder> {
private Context m_context;
private ArrayList<User> all_users;
public static final String EXTRA_HISUID = "NoHisUID";
public UserAdapter(Context context, ArrayList<User> all_users) {
this.m_context = context;
this.all_users = all_users;
}
#NonNull
#Override
public UserAdapter.UserViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(m_context);
View itemv = inflater.inflate(R.layout.layout_item_user, parent, false); //xml provide below
return new UserViewHolder(itemv);
}
public class UserViewHolder extends RecyclerView.ViewHolder{
public ImageView UserIcon; //default icon provided in xml
public TextView Username;
public UserViewHolder (View itemView){
super(itemView);
UserIcon = (ImageView)itemView.findViewById(R.id.usr_icon);
Username = (TextView)itemView.findViewById(R.id.tv_username);
}
}
public void onBindViewHolder(#NonNull UserAdapter.UserViewHolder holder, int position) {
User usr = all_users.get(position);
final String hisUID = usr.getUid();
holder.Username.setText(usr.getUsername());
if(usr.getIcon().equals("default_icon")){
holder.UserIcon.setImageResource(R.drawable.default_icon);
}
else{
Glide.with(m_context).load(usr.getIcon()).into(holder.UserIcon);
}
}
public int getItemCount() {
return all_users.size();
}
layout_item_user.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:padding="10dp"
android:layout_height="match_parent">
<ImageView
android:id="#+id/usr_icon"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="#mipmap/ic_launcher" />
<TextView
android:id="#+id/tv_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_marginLeft="13dp"
android:layout_toEndOf="#+id/usr_icon"
android:layout_toRightOf="#+id/usr_icon"
android:text="username"
android:textSize="18sp" />
<TextView
android:id="#+id/lastMessageTv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="The last message"
android:layout_marginStart="4dp"
android:maxLines="2"
android:layout_marginTop="3dp"
android:layout_toRightOf="#id/usr_icon"
android:layout_below="#id/tv_username"
android:layout_marginLeft="13dp" />
</RelativeLayout>
database:
users:
|-2NUPkQuHFRS49ZHDZzEtWiErIiv1
|-address: "920 West 4th Ave apt231"
|-city: "blank"
|-donut: 0
|-email: "not_busy#gmail.com"
|-full_name: "blank"
|-icon: "default_icon"
|-phone: "253353309"
|-state: "blank"
|-uid: "2NUPkQuHFRS49ZHDZzEtWiErIiv1"
|-username: "not_busy"
|-F0NRthr8uJPYMz2o129w2PAf30i1
|-GRJPA5hKA6aRgNl68sSxv3xruww1
|-W0PIUjUwRHXTkooztYFuhKuLItE3
|-cBzUNHceM2T47cr0zWX1tqgB2wA3
It must be a small bug, but I still cannot figure what problem is.. thank you in advance.

Fetching chat messages from firestore

I am making a chat section in my app, but the only problem I am facing is that whenever I enter a new message, some of the previous messages getting displayed in the recycler views get erased from the recycler view. But those messages are present in 'firestore'. They are not getting deleted from there but are getting vanished from the recycler view as soon as I enter a new message. When I restart the activity it works perfectly all messages are there.. but the problem only occurs when I enter a new message...and also when I scroll through the 'recyclerview'. Here are the codes...
This is the chatModel class :
import java.io.Serializable;
import java.util.Date;
public class chatModel implements Serializable {
private String Message,sender,Type,id;
private Date Time;
public chatModel()
{
}
public chatModel(String Message, String sender, String type,Date Time ,String id) {
this.Message = Message;
this.sender = sender;
Type = type;
this.Time = Time;
this.id = id;
}
public String getMessage() {
return Message;
}
public void setMessage(String message) {
Message = message;
}
public String getSender() {
return sender;
}
public void setSender(String sender) {
this.sender = sender;
}
public String getType() {
return Type;
}
public void setType(String type) {
Type = type;
}
public Date getTime() {
return Time;
}
public void setTime(Date time) {
Time = time;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
This is the DiscussionActivity class:
public class DiscussionActivity extends AppCompatActivity {
private FirebaseAuth mAuth;
private FirebaseFirestore mFirestore;
private FirebaseStorage mStorage;
private DatabaseReference mDatabase;
private EditText msg;
private Button sendBtn;
private ImageView addDocs;
private Uri imageUri;
private String url;
private RecyclerView mChatContainer;
private List<chatModel> chatList;
private chatAdapter adapter;
private int position=0;
String getMessage,getTitle,getDate;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_discussion);
mAuth = FirebaseAuth.getInstance();
mFirestore = FirebaseFirestore.getInstance();
mStorage = FirebaseStorage.getInstance();
mDatabase = FirebaseDatabase.getInstance().getReference();
msg = (EditText)findViewById(R.id.textContent);
sendBtn = (Button)findViewById(R.id.sendMsg);
addDocs = (ImageView)findViewById(R.id.include_documents);
getTitle = getIntent().getExtras().getString("Title");
int getCurrentYear = Calendar.getInstance().get(Calendar.YEAR);
int getCurrentMonth = Calendar.getInstance().get(Calendar.MONTH);
int getCurrentDate = Calendar.getInstance().get(Calendar.DATE);
getDate=getCurrentDate+getCurrentMonth+getCurrentYear+"";
mChatContainer = (RecyclerView)findViewById(R.id.chatContainer);
chatList = new ArrayList<>();
sendBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String message = msg.getText().toString().trim();
int random = new Random().nextInt();
Map chat = new HashMap();
chat.put("Message",message);
chat.put("sender",mAuth.getCurrentUser().getUid());
chat.put("Time",FieldValue.serverTimestamp());
chat.put("Type","text");
chat.put("id",String.valueOf(random));
mFirestore.collection("Ideas").document(getTitle).collection("Discussions").add(chat).addOnCompleteListener(DiscussionActivity.this, new OnCompleteListener() {
#Override
public void onComplete(#NonNull Task task) {
if(task.isSuccessful())
{
msg.setText("");
}
}
});
}
});
addDocs.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
discussionOptionsSheetDialog obj = new discussionOptionsSheetDialog();
Bundle bundle = new Bundle();
bundle.putString("Title",getTitle);
bundle.putString("id",mAuth.getCurrentUser().getUid());
obj.setArguments(bundle);
obj.show(getSupportFragmentManager(),"discussionOptionsBottomSheet");
}
});
adapter = new chatAdapter(chatList,getTitle);
Query first = mFirestore.collection("Ideas").document(getTitle).collection("Discussions").orderBy("Time");
first.addSnapshotListener(DiscussionActivity.this, new EventListener<QuerySnapshot>() {
#Override
public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {
if(!documentSnapshots.isEmpty())
{
for(DocumentChange doc:documentSnapshots.getDocumentChanges())
{
if(doc.getType()==DocumentChange.Type.ADDED)
{
chatModel obj = doc.getDocument().toObject(chatModel.class);
chatList.add(obj);
DocumentSnapshot lastVisible = documentSnapshots.getDocuments()
.get(documentSnapshots.size() -1);
Query next = mFirestore.collection("Ideas").document(getTitle).collection("Discussions")
.orderBy("Time").startAfter(lastVisible);
adapter.notifyDataSetChanged();
}
if(doc.getType()==DocumentChange.Type.MODIFIED)
{
String docID = doc.getDocument().getId();
chatModel obj = doc.getDocument().toObject(chatModel.class);
if(doc.getOldIndex() == doc.getNewIndex())
{
chatList.set(doc.getOldIndex(),obj);
}
else
{
chatList.remove(doc.getOldIndex());
chatList.add(doc.getNewIndex(),obj);
adapter.notifyItemMoved(doc.getOldIndex(),doc.getNewIndex());
}
adapter.notifyDataSetChanged();
}
}
}
}
});
LinearLayoutManager layoutManager = new LinearLayoutManager(DiscussionActivity.this);
layoutManager.setReverseLayout(false);
layoutManager.setStackFromEnd(false);
mChatContainer.setHasFixedSize(false);
mChatContainer.setLayoutManager(layoutManager);
mChatContainer.setAdapter(adapter);
}
}
This is the activity_discussion.xml file :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DiscussionActivity"
android:background="#6D7993">
<android.support.v7.widget.RecyclerView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_above="#id/writingSection"
android:id="#+id/chatContainer"
android:layout_marginRight="5dp">
</android.support.v7.widget.RecyclerView>
<RelativeLayout
android:id="#+id/writingSection"
android:layout_width="379dp"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:background="#drawable/chat_background">
<EditText
android:id="#+id/textContent"
android:layout_width="342dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginLeft="0dp"
android:layout_toLeftOf="#id/include_documents"
android:hint="Write here.." />
<ImageView
android:layout_width="wrap_content"
android:layout_height="28dp"
android:src="#drawable/include_docs"
android:id="#+id/include_documents"
android:layout_toLeftOf="#id/sendMsg"
android:layout_marginTop="9dp"
android:layout_marginRight="3dp"/>
<Button
android:id="#+id/sendMsg"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_alignParentRight="true"
android:layout_marginRight="2dp"
android:layout_marginTop="7dp"
android:background="#drawable/send_message" />
</RelativeLayout>
This is the chatAdapter class :
public class chatAdapter extends
RecyclerView.Adapter<chatAdapter.ViewHolder> {
private FirebaseAuth mAuth;
private FirebaseFirestore mFirestore;
private Context context;
private List<chatModel> chatMsgs;
private String title;
public chatAdapter(List<chatModel> chatMsgs,String title) {
this.chatMsgs = chatMsgs;
this.title = title;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int
viewType) {
mAuth = FirebaseAuth.getInstance();
mFirestore = FirebaseFirestore.getInstance();
context = parent.getContext();
View view =
LayoutInflater.from(context).inflate(R.layout.chat_box_layout,null);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, final
int position) {
String getSenderId = chatMsgs.get(position).getSender();
final String getSenderMessage =
chatMsgs.get(position).getMessage();
final String getID = chatMsgs.get(position).getId();
final String theType = chatMsgs.get(position).getType();
if(theType.equals("text"))
{
if(getSenderId.equals(mAuth.getCurrentUser().getUid()))
{
holder.aBox.setVisibility(View.GONE);
holder.oIbox.setVisibility(View.GONE);
holder.mIbox.setVisibility(View.GONE);
//To get name...
mFirestore.collection("Users").document(getSenderId).get()
.addOnCompleteListener((Activity) context, new
OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull
Task<DocumentSnapshot> task) {
if(task.isSuccessful())
{
String getFirstName =
task.getResult().getString("Firstname");
String getLastName =
task.getResult().getString("Lastname");
holder.mName.setText(getFirstName.charAt(0)+getFirstName.substring(1).toLo . werCase());
}
}
});
holder.mContent.setText(getSenderMessage);
}
if(!getSenderId.equals(mAuth.getCurrentUser().getUid())) {
holder.mBox.setVisibility(View.GONE);
holder.aEdit.setVisibility(View.GONE);
holder.aDelete.setVisibility(View.GONE);
holder.oIbox.setVisibility(View.GONE);
holder.mIbox.setVisibility(View.GONE);
//To get name...
mFirestore.collection("Users").document(getSenderId).get()
.addOnCompleteListener((Activity) context, new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
String getFirstName = task.getResult().getString("Firstname");
String getLastName = task.getResult().getString("Lastname");
holder.aName.setText(getFirstName.charAt(0) + getFirstName.substring(1).toLowerCase());
}
}
});
holder.aContent.setText(getSenderMessage);
}
}
}
#Override
public int getItemCount() {
return chatMsgs.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
//Variables for my chat lists...
private TextView mName,mContent;
private ImageView mDelete,mEdit;
private RelativeLayout mBox;
//Variable for other person's chat lists....
private TextView aName,aContent;
private ImageView aDelete,aEdit;
private RelativeLayout aBox;
//Variables for my images list..
private RelativeLayout mIbox;
private ImageView myImage,mIDelete;
private TextView myNameInImage;
//Variables for others image list..
private RelativeLayout oIbox;
private ImageView othersImage,oIDelete;
private TextView othersNameInImage;
public ViewHolder(View itemView) {
super(itemView);
//My variable initialization
mName = (TextView)itemView.findViewById(R.id.name);
mContent = (TextView)itemView.findViewById(R.id.chatContent);
mDelete = (ImageView)itemView.findViewById(R.id.delete);
mEdit = (ImageView)itemView.findViewById(R.id.editContent);
mBox = (RelativeLayout)itemView.findViewById(R.id.userChatBox);
//Other people's variables initialization..
aName = (TextView)itemView.findViewById(R.id.othersName);
aContent = (TextView)itemView.findViewById(R.id.othersChatContent);
aDelete = (ImageView)itemView.findViewById(R.id.othersDelete);
aEdit = (ImageView)itemView.findViewById(R.id.othersEditContent);
aBox = (RelativeLayout)itemView.findViewById(R.id.othersChatBox);
}
}
by this
but the only problem i am facing is that whenever i enter a new message...
I assume you mean getting messages when click sendBtn. Considering you code, fetching messages will happen only when OnCreate() raises (When app starts) >> So, it happens only once!
What you have to do is put first.addSnapshotListener() in a separate void and call in OnCreate() as well as sendBtn.setOnClickListener().
I hope I am being clear, and GOOD LUCK!
Apparently i changed my single chat box item layout, like i tried to make the current user chatbox(My message) and the other user chatbox in the same layout and tried to hide it accordingly...As soon as I changed it that is i made two separate layouts :
1. my_chatbox - To show my messages
2. other_chatbox.xml - For others to send a message..
and altered my adapter accordingly....
And it works now, even for the images. :)
here are codes : -
my_chatbox.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RelativeLayout
android:id="#+id/userChatBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:layout_alignParentTop="true">
<RelativeLayout
android:id="#+id/chatBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginLeft="5dp"
android:background="#drawable/chat_background">
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="20dp"
android:text="Name"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Medium"
android:textColor="#000000"
android:textStyle="bold" />
<TextView
android:id="#+id/chatContent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/name"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="20dp"
android:text="Content"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Medium"
android:textColor="#000000" />
</RelativeLayout>
<ImageView
android:id="#+id/delete"
android:layout_width="25dp"
android:layout_height="15dp"
android:layout_alignEnd="#+id/chatBox"
android:layout_below="#+id/chatBox"
android:layout_marginTop="-10dp"
android:src="#drawable/delete" />
<ImageView
android:id="#+id/editContent"
android:layout_width="25dp"
android:layout_height="15dp"
android:layout_below="#+id/chatBox"
android:layout_marginTop="-10dp"
android:layout_toStartOf="#+id/delete"
android:src="#drawable/edit"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Small"
/>
</RelativeLayout>
</RelativeLayout>
the other_user_chatbox.xml :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/userChatBox"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/chatBox"
android:layout_marginLeft="5dp"
android:layout_marginBottom="10dp"
android:background="#drawable/chat_background"
android:backgroundTint="#F4DDBB">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/name"
android:text="Name"
android:textColor="#000000"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Medium"
android:textStyle="bold"
android:layout_marginLeft="10dp"
android:layout_marginRight="20dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/name"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Medium"
android:id="#+id/chatContent"
android:text="Content"
android:textColor="#000000"
android:layout_marginLeft="10dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="10dp"/>
</RelativeLayout>
<ImageView
android:id="#+id/othersDelete"
android:layout_width="25dp"
android:layout_height="15dp"
android:layout_below="#id/chatBox"
android:src="#drawable/delete" />
<ImageView
android:layout_width="25dp"
android:layout_height="15dp"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Small"
android:layout_below="#id/chatBox"
android:layout_toRightOf="#id/othersDelete"
android:src="#drawable/edit"
android:layout_marginRight="3dp"
android:id="#+id/othersEditContent"/>
</RelativeLayout>
</RelativeLayout>
Just try to keep the id's same in both the xml so as to make your viewHolder less complex.
And this is my chatAdapter.class :
public class chatAdapter extends RecyclerView.Adapter<chatAdapter.ViewHolder> {
private FirebaseAuth mAuth;
private FirebaseFirestore mFirestore;
private Context context;
private static final int SENT = 0;
private static final int RECEIVED = 1;
private String userID;
private List<chatModel> chatMsgs;
private String title;
public chatAdapter(List<chatModel> chatMsgs,String title,String userID) {
this.chatMsgs = chatMsgs;
this.title = title;
this.userID = userID;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
mAuth = FirebaseAuth.getInstance();
mFirestore = FirebaseFirestore.getInstance();
context = parent.getContext();
View view = null;
if(viewType == SENT)
{
view =
LayoutInflater.from(context).inflate(R.layout.chat_box_layout,parent,false);
}
if(viewType == RECEIVED)
{
view =
LayoutInflater.from(context).inflate(R.layout.other_user_chat_box,parent,false);
}
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, final int position) {
String getSenderId = chatMsgs.get(position).getSender();
final String getSenderMessage = chatMsgs.get(position).getMessage();
final String getID = chatMsgs.get(position).getId();
final String theType = chatMsgs.get(position).getType();
if(theType.equals("text"))
{
//To get name...
mFirestore.collection("Users").document(getSenderId).get()
.addOnCompleteListener((Activity) context, new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
String getFirstName = task.getResult().getString("Firstname");
String getLastName = task.getResult().getString("Lastname");
holder.mName.setText(getFirstName.charAt(0) + getFirstName.substring(1).toLowerCase());
}
}
});
holder.mContent.setText(getSenderMessage);
}
}
#Override
public int getItemCount() {
return chatMsgs.size();
}
#Override
public int getItemViewType(int position) {
if (chatMsgs.get(position).getSender() . equals(userID))
return SENT;
else
return RECEIVED;
}
public class ViewHolder extends RecyclerView.ViewHolder{
//Variables for my chat lists...
private TextView mName,mContent;
private ImageView mDelete,mEdit;
private RelativeLayout mBox;
public ViewHolder(View itemView) {
super(itemView);
//variable initialization
mName = (TextView)itemView.findViewById(R.id.name);
mContent = (TextView)itemView.findViewById(R.id.chatContent);
mDelete = (ImageView)itemView.findViewById(R.id.delete);
mEdit = (ImageView)itemView.findViewById(R.id.editContent);
mBox = (RelativeLayout)itemView.findViewById(R.id.userChatBox);
}
}
}
Hope it helps anyone else with the same problems and others too if they are interested.. :)

RecyclerView doesn't load items on first start of activity

Everytime we open the activity that bares the recycler adapter it fails to load on the first try. Exiting the activity and re-entering fixes the problem. Here is a gif for example. https://gyazo.com/32dc664dd427ef1129704a09861a3708
The Item i am spawning in:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:card_view="http://schemas.android.com/tools"
android:id="#+id/show_chat_single_item_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<android.support.v7.widget.CardView
android:layout_width="match_parent"
android:layout_height="70dp"
app:cardBackgroundColor="#dcdada"
app:cardCornerRadius="0dp"
app:contentPadding="3dp"
card_view:cardCornerRadius="5dp"
card_view:cardElevation="2dp"
card_view:cardUseCompatPadding="true">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/chat_persion_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#mipmap/ic_launcher" />
<TextView
android:id="#+id/chat_persion_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="0dp"
android:text="Name"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintLeft_toRightOf="#+id/chat_persion_image"
app:layout_constraintTop_toTopOf="#+id/chat_persion_image" />
<TextView
android:id="#+id/chat_persion_email"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="0dp"
android:layout_marginTop="8dp"
android:text="Email"
app:layout_constraintLeft_toLeftOf="#+id/chat_persion_name"
app:layout_constraintTop_toBottomOf="#+id/chat_persion_name" />
</android.support.constraint.ConstraintLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
My conversation layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/msgs_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:theme="#style/AppTheme2"
>
<android.support.v7.widget.RecyclerView
android:id="#+id/active_chats"
android:layout_width="match_parent"
android:layout_height="510dp"
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginLeft="2dp"
android:layout_marginRight="2dp"
android:layout_marginTop="57dp">
</android.support.v7.widget.RecyclerView>
<include
android:id="#+id/include2"
layout="#layout/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</RelativeLayout>
My Adapter:
public class ActiveChatConvo extends RecyclerView.Adapter<ActiveChatConvo.ViewHolder>
{
private ArrayList<User> mUsers;
private Context mContext;
public ActiveChatConvo(ArrayList<User> photos,Context dick) {
mUsers = photos;
mContext = dick;
}
private Context getContext() {
return mContext;
}
#Override
public ActiveChatConvo.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
// Inflate the custom layout
View contactView = inflater.inflate(R.layout.chat_single_item, parent, false);
// Return a new holder instance
ViewHolder viewHolder = new ViewHolder(contactView);
return viewHolder;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// Get the data model based on position
User user = mUsers.get(position);
// Set item views based on your views and data model
TextView name = holder.mItemName;
name.setText(user.getName());
TextView description = holder.mItemDescription;
description.setText(user.getEmail());
ImageView pic = holder.mItemImage;
Picasso.with(pic.getContext()).load(Uri.parse(user.getPic())).into(pic);
}
#Override
public int getItemCount() {
return mUsers.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private ImageView mItemImage;
private TextView mItemName;
private TextView mItemDescription;
private LinearLayout layout;
final LinearLayout.LayoutParams params;
public ViewHolder(View v) {
super(v);
mItemImage = (ImageView) v.findViewById(R.id.chat_persion_image);
mItemName = (TextView) v.findViewById(R.id.chat_persion_name);
mItemDescription = (TextView) v.findViewById(R.id.chat_persion_email);
layout = (LinearLayout) itemView.findViewById(R.id.show_chat_single_item_layout);
params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
v.setOnClickListener(this);
}
#Override
public void onClick(View v) {
Context context = itemView.getContext();
Intent showChatIntent = new Intent(context, ChatConversationActivity.class);
//showPhotoIntent.putExtra(PHOTO_KEY, mPhoto);
context.startActivity(showChatIntent);
}
}
}
My main class
public class ConnectionsActivity extends AppCompatActivity {
private Toolbar toolbar;
private ViewPager mViewPager;
private TextView person_name,person_email;
private RecyclerView recyclerView;
private DatabaseReference mRef;
private LinearLayoutManager mLinearLayoutManager;
private ArrayList<User> users;
private FirebaseAuth mAuth;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_connections);
//Database
mRef = FirebaseDatabase.getInstance().getReference("Users");
mRef.keepSynced(true);
mAuth = FirebaseAuth.getInstance();
FirebaseUser user = mAuth.getCurrentUser();
users = new ArrayList<>();
mRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists())
{
for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
String name = postSnapshot.child("Name").getValue(String.class);
String email = postSnapshot.child("Email").getValue(String.class);
String pic = postSnapshot.child("image").getValue(String.class);
users.add(new User(name,email,pic));
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
//Recycler View
recyclerView = (RecyclerView)findViewById(R.id.active_chats);
ActiveChatConvo adapter = new ActiveChatConvo(users,this);
recyclerView.setAdapter(adapter);
mLinearLayoutManager = new LinearLayoutManager(this);
//mLinearLayoutManager.setStackFromEnd(true);
recyclerView.setLayoutManager(mLinearLayoutManager);
//VIEWS
toolbar = (Toolbar) findViewById(R.id.tToolbar);
if (toolbar != null)
setSupportActionBar(toolbar);
ImageView profileActivity = (ImageView) toolbar.findViewById(R.id.action_profile);
ImageView homeActivity = (ImageView) toolbar.findViewById(R.id.action_home);
profileActivity.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent profileActivity = new Intent(ConnectionsActivity.this, ProfileActivity.class);
startActivity(profileActivity);
finish();
overridePendingTransition(R.anim.push_right_in, R.anim.push_right_out);
}
});
homeActivity.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent home = new Intent(ConnectionsActivity.this, HomeActivity.class);
startActivity(home);
finish();
overridePendingTransition(R.anim.push_right_in, R.anim.push_right_out);
}
});
}
}
So if the recyclerView Activity is the first activity I visit then it will not create the items.
Firebase is synchronize so it doesn't block the main thread of your application, that mean that your application continue executing, you need to notify the adapter after firebase finishing his job by using adapter.notifiyDatasetChanged() after the for loop
Replace this:
recyclerView = (RecyclerView)findViewById(R.id.active_chats);
ActiveChatConvo adapter = new ActiveChatConvo(users,this);
recyclerView.setAdapter(adapter);
mLinearLayoutManager = new LinearLayoutManager(this);
//mLinearLayoutManager.setStackFromEnd(true);
recyclerView.setLayoutManager(mLinearLayoutManager);
with this:
recyclerView = (RecyclerView)findViewById(R.id.active_chats);
ActiveChatConvo adapter = new ActiveChatConvo(users,this);
mLinearLayoutManager = new LinearLayoutManager(this);
//mLinearLayoutManager.setStackFromEnd(true);
recyclerView.setLayoutManager(mLinearLayoutManager);
recyclerView.setAdapter(adapter);
You need to set adapter after you set LayoutManager.
In my case I managed to solve it I found a way to start FirebaseDatabase before opening the activity and added the cod
adapter.notifyDataSetChanged();
and then I started the firebase before opening it with this
FirebaseDatabase.getInstance().getReference().keepSynced(true);
You can use Boolean button to check if it is true adapter is made

Android firebase - why does clicking star always remove one child value?

This is FreeboardPost.java
public class FreeboardPost
{
public String imageUrl;
public String uid;
public String author;
public String title;
public String body;
public int starCount = 0;
public Map<String, Boolean> stars = new HashMap<>();
public FreeboardPost()
{
}
public FreeboardPost(String uid, String author, String title, String body, String imageUrl)
{
this.imageUrl = imageUrl;
this.uid = uid;
this.author = author;
this.title = title;
this.body = body;
}
#Exclude
public Map<String, Object> toMap()
{
HashMap<String, Object> result = new HashMap<>();
result.put("image", imageUrl);
result.put("uid", uid);
result.put("author", author);
result.put("title", title);
result.put("body", body);
result.put("starCount", starCount);
result.put("stars", stars);
return result;
}
}
This is FreeboardPostViewHolder.java
public class FreeboardPostViewHolder extends RecyclerView.ViewHolder
{
public TextView freeboardtitleView;
public TextView freeboardauthorView;
public ImageView freeboardstarView;
public TextView freeboardnumStarsView;
public TextView freeboardbodyView;
public CircleImageView freeboardprofileView;
public FreeboardPostViewHolder(View itemView)
{
super(itemView);
freeboardtitleView = (TextView) itemView.findViewById(R.id.freeboard_post_title);
freeboardauthorView = (TextView) itemView.findViewById(R.id.freeboard_post_author);
freeboardstarView = (ImageView)itemView.findViewById(R.id.freeboard_star);
freeboardnumStarsView = (TextView)itemView.findViewById(R.id.freeboard_post_num_stars);
freeboardbodyView = (TextView)itemView.findViewById(R.id.freeboard_post_body);
freeboardprofileView = (CircleImageView)itemView.findViewById(R.id.freeboard_post_author_photo);
}
public void bindToPost(FreeboardPost freeboardpost, View.OnClickListener starClickListener)
{
freeboardtitleView.setText(freeboardpost.title);
freeboardauthorView.setText(freeboardpost.author);
freeboardnumStarsView.setText(String.valueOf(freeboardpost.starCount));
freeboardbodyView.setText(freeboardpost.body);
freeboardstarView.setOnClickListener(starClickListener);
}
}
and this is FreeboardPostListFragment.java
public abstract class FreeboardPostListFragment extends Fragment
{
private static final String TAG = "FreeBoardPostListFragment";
private DatabaseReference mDatabase;
private FirebaseRecyclerAdapter<FreeboardPost, FreeboardPostViewHolder> mAdapter;
private RecyclerView mRecycler;
private LinearLayoutManager mManager;
private DatabaseReference mPostReference;
private ValueEventListener mPostListener;
private String image;
public FreeboardPostListFragment()
{
}
#Override
public View onCreateView (LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
super.onCreateView(inflater, container, savedInstanceState);
View rootView = inflater.inflate(R.layout.freeboard_fragment_all_posts, container, false);
mDatabase = FirebaseDatabase.getInstance().getReference();
mRecycler = (RecyclerView)rootView.findViewById(R.id.freeboard_messages_list);
mRecycler.setHasFixedSize(true);
return rootView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
mManager = new LinearLayoutManager(getActivity());
mManager.setReverseLayout(true);
mManager.setStackFromEnd(true);
mRecycler.setLayoutManager(mManager);
Query postsQuery = getQuery(mDatabase);
mAdapter = new FirebaseRecyclerAdapter<FreeboardPost, FreeboardPostViewHolder>(FreeboardPost.class, R.layout.freeboard_item_post, FreeboardPostViewHolder.class, postsQuery)
{
#Override
protected void populateViewHolder(final FreeboardPostViewHolder viewHolder, final FreeboardPost model, final int position)
{
final DatabaseReference postRef = getRef(position);
final String postKey = postRef.getKey();
mPostReference = FirebaseDatabase.getInstance().getReference().child("FreeboardPost").child(postKey);
viewHolder.itemView.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
Intent intent = new Intent(getActivity(), FreeBoardPostDetailActivity.class);
intent.putExtra(FreeBoardPostDetailActivity.EXTRA_POST_KEY, postKey);
startActivity(intent);
}
});
if(model.stars.containsKey(getUid()))
{
viewHolder.freeboardstarView.setImageResource(R.drawable.ic_toggle_star_24);
}
else
{
viewHolder.freeboardstarView.setImageResource(R.drawable.ic_toggle_star_outline_24);
}
viewHolder.bindToPost(model, new View.OnClickListener()
{
#Override
public void onClick(View starView)
{
DatabaseReference globalPostRef = mDatabase.child("FreeboardPost").child(postRef.getKey());
DatabaseReference userPostRef = mDatabase.child("FreeboardUserPost").child(model.uid).child(postRef.getKey());
onStarClicked(globalPostRef);
onStarClicked(userPostRef);
}
});
}
};
mRecycler.setAdapter(mAdapter);
}
private void onStarClicked(DatabaseReference postRef)
{
postRef.runTransaction(new Transaction.Handler()
{
#Override
public Transaction.Result doTransaction(MutableData mutableData)
{
FreeboardPost p = mutableData.getValue(FreeboardPost.class);
if(p == null)
{
return Transaction.success(mutableData);
}
if(p.stars.containsKey(getUid()))
{
p.starCount = p.starCount - 1;
p.stars.remove(getUid());
}
else
{
p.starCount = p.starCount + 1;
p.stars.put(getUid(), true);
}
mutableData.setValue(p);
return Transaction.success(mutableData);
}
#Override
public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot)
{
}
});
}
public String getUid()
{
return FirebaseAuth.getInstance().getCurrentUser().getUid();
}
public abstract Query getQuery(DatabaseReference databaseReference);
}
and this is freeboard_include_post_author.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:gravity="center_vertical"
android:orientation="horizontal">
<de.hdodenhof.circleimageview.CircleImageView
android:id="#+id/freeboard_post_author_photo"
android:layout_width="40dp"
android:layout_height="40dp"
app:civ_border_width="2dp"
app:civ_border_color="#FF000000">
</de.hdodenhof.circleimageview.CircleImageView>
<TextView
android:id="#+id/freeboard_post_author"
style="#style/Base.TextAppearance.AppCompat.Small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:gravity="center_vertical"
tools:text="someauthor#email.com" />
</LinearLayout>
and this is freeboard_item_post.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="1dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp">
<ImageView
android:id="#+id/freeboard_post_image"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_marginRight="10dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:scaleType="centerCrop"
android:src="#drawable/profile"/>
<RelativeLayout
android:id="#+id/freeboard_text_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="#id/freeboard_post_image">
<LinearLayout
android:id="#+id/freeboard_star_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/freeboard_post_author_layout"
android:layout_alignParentRight="true"
android:layout_alignTop="#+id/freeboard_post_author_layout"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="#+id/freeboard_star"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="5dp"
android:background="?attr/selectableItemBackground"
android:src="#drawable/ic_toggle_star_outline_24" />
<TextView
android:id="#+id/freeboard_post_num_stars"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
tools:text="7" />
</LinearLayout>
<include
android:id="#+id/freeboard_post_text"
layout="#layout/freeboard_include_post_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_marginLeft="5dp"
android:layout_marginTop="10dp" />
<include
android:id="#+id/freeboard_post_author_layout"
android:layout_below="#+id/freeboard_post_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
layout="#layout/freeboard_include_post_author"
android:layout_marginTop="10dp"
android:layout_alignParentLeft="true" />
</RelativeLayout>
</RelativeLayout>
</android.support.v7.widget.CardView>
Thank you so much for reading my long codes. I was having a hard time displaying user's image with star button with it. When I click star, the firebase immediately deletes "image" value from the same child.
This is before I click star
and this is after I click star button.
I am 100% sure there is no code that deletes the child or value.. but why does it remove my image address from the child..? I am so curious about it. Thank you!
You didn't post the code that creates instances of FreeboardPost in the database. I'm guessing that you are using toMap() because it stores the image URL in a field named image, which appears in the database sample you posted.
In your transaction you are using Firebase to serialize/deserialize FreeboardPost. It expects to find the image URL in a field named imageUrl, because that is the public field name in your class. When the node you posted is read, there is no field named imageUrl so the created instance of FreeboardPost has null for that field value. When the instance is written, there is no value written for imageUrlbecause it is null, and the previous database value for image is lost because FreeboardPost has no field with that name.
If you want to use the Firebase capabilities to serialize/deserialize your FreeboardPost, you should use them for all database reads and writes. Using updateMap() or setValue() with a map to write instances and then a POJO class to read risks naming mismatches.

Categories

Resources