I am trying to build chat feature in my android app. I am using the Recycler view to show the chat history. But when I call the RecyclerView adapter, it only calls the constructor and the getItemCount() method which returns 4 (which is correct). Can someone please help me. Here's the code.
I read that calling the setLayoutManager() after the set adapter method could fix the problem but it didn't work for me.
Already tried this RecyclerView not calling onCreateViewHolder or onBindView
public class MessageListActivity extends AppCompatActivity {
private static final int ACTIVITY_NUM = 1;
private RecyclerView mMessageRecycler;
private MessageListAdapter mMessageAdapter;
private Button mSendButton;
private EditText mTextbox;
List<Message> messageList = new ArrayList<>();
private ChatListItem chat;
Context context;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_message_list);
Intent i = getIntent();
chat = (ChatListItem) i.getSerializableExtra("CHAT");
mMessageRecycler = (RecyclerView) findViewById(R.id.reyclerview_message_list);
mSendButton = (Button) findViewById(R.id.button_chatbox_send);
mTextbox = (EditText) findViewById(R.id.edittext_chatbox);
sendMessage(mSendButton);
//creating bottom navigation view
setupBottomNavigationView();
DatabaseReference mRef = FirebaseDatabase.getInstance().getReference().child("Chat").child(chat.getChatId());
mRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
Iterable<DataSnapshot> children = dataSnapshot.getChildren();
for(DataSnapshot child: children){
messageList.add(child.getValue(Message.class));
}
Log.d("testing0 ListActivity", messageList.toString());
mMessageAdapter = new MessageListAdapter(MessageListActivity.this, messageList);
mMessageRecycler.setAdapter(mMessageAdapter);
mMessageRecycler.setLayoutManager(new LinearLayoutManager(getBaseContext()));
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
/**
* BottomNavigationView setup
*/
private void setupBottomNavigationView() {
Log.d("MessageListActivity", "setupBottomNavigationView: setting up BottomNavigationView");
BottomNavigationView bottomNavigationView = findViewById(R.id.bottomNavViewBar);
BottomNavigationViewHelper.enableNavigation(MessageListActivity.this,bottomNavigationView);
Menu menu = bottomNavigationView.getMenu();
MenuItem menuItem = menu.getItem(ACTIVITY_NUM);
menuItem.setChecked(true);
}
private void sendMessage(Button button){
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
String content = mTextbox.getText().toString().trim();
if (content.length() > 0) {
Message newMessage = new Message();
newMessage.setTextMessage(mTextbox.getText().toString());
newMessage.setIdSender(chat.getCustomerPhone());
newMessage.setIdReceiver(chat.getDriverPhone());
newMessage.setTimestamp(System.currentTimeMillis());
FirebaseDatabase.getInstance().getReference().child("Chat").child(chat.getChatId()).push().setValue(newMessage);
mTextbox.setText("");
}
}
});
}
}
public class MessageListAdapter extends RecyclerView.Adapter {
private static final int VIEW_TYPE_MESSAGE_SENT = 1;
private static final int VIEW_TYPE_MESSAGE_RECEIVED = 2;
private Context mContext;
//private List<BaseMessage> mMessageList;
private List<Message> mMessageList;
//get current user
private String phone_Number;
private FirebaseAuth mauth = FirebaseAuth.getInstance();
private FirebaseUser user = mauth.getCurrentUser();
public MessageListAdapter(Context context, List<Message> messageList) {
Log.d("testing3 messageAdapter", "inside constructor");
mContext = context;
mMessageList = messageList;
}
@Override
public int getItemCount() {
Log.d("testing4 messageAdapter", String.valueOf(mMessageList.size()));
return mMessageList.size();
}
// Determines the appropriate ViewType according to the sender of the message.
@Override
public int getItemViewType(int position) {
Log.d("testing0 messageAdaper", "inside messageListAdapter");
Message message = (Message) mMessageList.get(position);
phone_Number = user.getPhoneNumber();
if (message.getIdSender().equals(phone_Number)) {
// If the current user is the sender of the message
return VIEW_TYPE_MESSAGE_SENT;
} else {
// If some other user sent the message
return VIEW_TYPE_MESSAGE_RECEIVED;
}
}
// Inflates the appropriate layout according to the ViewType.
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
Log.d("testing1 messageAdapter", "inside onCreateViewHolder");
if (viewType == VIEW_TYPE_MESSAGE_SENT) {
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_message_sent, parent, false);
return new SentMessageHolder(view);
} else if (viewType == VIEW_TYPE_MESSAGE_RECEIVED) {
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_message_received, parent, false);
return new ReceivedMessageHolder(view);
}
return null;
}
// Passes the message object to a ViewHolder so that the contents can be bound to UI.
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
Message message = (Message) mMessageList.get(position);
Log.d("testing2 messageAdaper", "inside onBindViewHolder");
switch (holder.getItemViewType()) {
case VIEW_TYPE_MESSAGE_SENT:
((SentMessageHolder) holder).bind(message);
break;
case VIEW_TYPE_MESSAGE_RECEIVED:
((ReceivedMessageHolder) holder).bind(message);
}
}
private class SentMessageHolder extends RecyclerView.ViewHolder {
TextView messageText, timeText;
SentMessageHolder(View itemView) {
super(itemView);
messageText = (TextView) itemView.findViewById(R.id.text_message_body);
timeText = (TextView) itemView.findViewById(R.id.text_message_time);
}
void bind(Message message) {
messageText.setText(message.getTextMessage());
// Format the stored timestamp into a readable String using method.
timeText.setText(new SimpleDateFormat("hh:mm KK").format(new Date(message.getTimestamp())));
}
}
private class ReceivedMessageHolder extends RecyclerView.ViewHolder {
TextView messageText, timeText;
ReceivedMessageHolder(View itemView) {
super(itemView);
messageText = (TextView) itemView.findViewById(R.id.text_message_body);
timeText = (TextView) itemView.findViewById(R.id.text_message_time);
}
void bind(Message message) {
messageText.setText(message.getTextMessage());
timeText.setText(new SimpleDateFormat("hh:mm KK").format(new Date(message.getTimestamp())));
}
}
XML
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
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=".MessageActivity.MessageListActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/reyclerview_message_list"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent">
</androidx.recyclerview.widget.RecyclerView>
<!-- A horizontal line between the chatbox and RecyclerView -->
<View
android:layout_width="0dp"
android:layout_height="2dp"
android:background="#dfdfdf"
android:layout_marginBottom="0dp"
app:layout_constraintBottom_toTopOf="@+id/layout_chatbox"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
<LinearLayout
android:id="@+id/layout_chatbox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:minHeight="48dp"
android:background="#ffffff"
app:layout_constraintBottom_toTopOf="@id/navBarContainer"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent">
<EditText
android:id="@+id/edittext_chatbox"
android:hint="Enter message"
android:background="@android:color/transparent"
android:layout_gravity="center"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:maxLines="6"/>
<Button
android:id="@+id/button_chatbox_send"
android:text="SEND"
android:textSize="14dp"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:layout_width="64dp"
android:layout_height="48dp"
android:gravity="center"
android:layout_gravity="bottom" />
</LinearLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/navBarContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent">
<include layout="@layout/layout_navbar" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>