我正在尝试在我的Android应用中建立聊天功能。我正在使用“回收站”视图来显示聊天记录。但是,当我调用RecyclerView适配器时,它仅调用构造函数和getItemCount()方法,该方法返回4(正确)。有人可以帮帮我吗。这是代码。
我了解到,在设置适配器方法之后调用setLayoutManager()可以解决问题,但对我不起作用。
已经尝试过此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>
答案 0 :(得分:0)
在设置适配器之前尝试设置LayoutManager
mMessageRecycler.setLayoutManager(new LinearLayoutManager(MessageListActivity.this,RecyclerView.VERTICAL,false));
mMessageRecycler.setAdapter(mMessageAdapter);
答案 1 :(得分:0)
在onCreate()
中而不是在ValueEventListener回调中设置RecyclerView:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
mMessageAdapter = new MessageListAdapter(MessageListActivity.this, messageList);
mMessageRecycler.setAdapter(mMessageAdapter);
mMessageRecycler.setLayoutManager(new LinearLayoutManager(getBaseContext()));
然后在ValueEventListener回调中,只需将消息添加到列表中并调用mMessageAdapter.notifyDatasetChanged()
:
@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.notifyDatasetChanged();
}