我已经构建了一个聊天应用程序,我正在添加发送到recyclerview的消息,然后再传递它。我想添加一个状态,如whatsApp(勾选发送,如果发生错误,则显示错误)。这是我的发送消息代码: 在发送消息中,我正在这样做:
public void sendMessage(final String myUId, String chatterUId, final String messageType, final String messageText) {
if (messageText != null && !messageText.trim().equals("")) {
//String messageType = "text"; // it is text by default
//To update the conversation entry with latest message
if (convId == null || convId.equals("")) {
//generate push key as the conv Id
convId = myConvRef.push().getKey();
}
final FirebaseDatabase rootDB = FirebaseDatabase.getInstance();
final DatabaseReference messagesReference = rootDB.getReference()
.child(FirebaseValues.MESSAGES_TABLE)
.child(convId);
sentMessagePushKey = messagesReference.push().getKey();
sentMessage = new Message(messageText, messageType, myUId);
messages.add(sentMessage);
messagesKey.add(sentMessagePushKey);
messageET.setText("");
messagesAdapter.notifyDataSetChanged();
messageRv.scrollToPosition(messages.size() - 1);
//Not posting full code due to stackoverflow word restriction
}
loadMessages函数是:
private void loadMessages() {
Log.d(TAG, "Inside loadMessages()");
messagesRef = FirebaseDatabase.getInstance().getReference().child(FirebaseValues.MESSAGES_TABLE).child(convId);
Query messagesQuery = messagesRef.limitToLast(TOTAL_ITEM_EACH_LOAD).orderByKey();
messagesQuery.addChildEventListener(new ChildEventListener() {
@Override
public void onChildAdded(@NonNull DataSnapshot ds, @Nullable String s) {
Log.d(TAG, "Current Message Key: " + ds.getKey());
if (itemPos++ == 0) {
lastKey = ds.getKey();
}
Log.d(TAG, "last item key is: " + lastKey);
Message message = ds.getValue(Message.class);
if(!sentMessagePushKey.equals(ds.getKey())){
messages.add(message);
messagesKey.add(ds.getKey());
}
else{
//The message has been updated in db successfully
messagesAdapter.updateSent(true);
}
//messages.add(message);
/*if(topicKey!=null){
messagesKey.add(0,null);
messages.add(0,null);
}*/
messagesAdapter.notifyDataSetChanged();
messageRv.scrollToPosition(messages.size() - 1);
}
@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) {
messagesAdapter.updateSent(false);
}
});
}
添加孩子后,我想更新在recylerview项目上显示已发送的滴答声。
MessagesAdapter:
public class MessagesAdapter extends RecyclerView.Adapter<MessagesAdapter.MessageViewHolder> {
//Other content i.e message
private static final int CONTENT = 0;
//Topic content
private static final int TOPIC_TYPE = 1;
//My message
private static final int MY_MESSAGE = 2;
//My Image message
private static final int MY_IMAGE_MESSAGE = 3;
//My Voice note
private static final int MY_VOICE_NOTE = 4;
//Other person's messages
private static final int OTHER_IMAGE_MESSAGE = 5;
private static final int OTHER_VOICE_TYPE = 6;
private static final String TAG = "MessageAdapterTAG" ;
static final int PERMISSION_STORAGE = 99;
private ArrayList<Message> messages;
private Context mContext;
private FirebaseDatabase mDb;
private ArrayList<String> messagesKey;
private String topicKey;
private String convId;
private String myUId;
private boolean tag = false;
float ratingVal = -1;
int noOfRates=0;
public MessagesAdapter(Context context, ArrayList<Message> messages, ArrayList<String> messagesKey,String myUId, String convId, String topicKey) {
mContext = context;
this.messages = messages;
mDb = FirebaseDatabase.getInstance();
this.messagesKey = messagesKey;
this.myUId = myUId;
this.convId = convId;
this.topicKey = topicKey;
}
View view = null;
@Override
public MessagesAdapter.MessageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(viewType==TOPIC_TYPE){
//User came through topic
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.topic_chat_layout, parent, false);
AbsListView.LayoutParams params = new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT,
AbsListView.LayoutParams.WRAP_CONTENT);
view.setLayoutParams(params);
}
else if(viewType==MY_MESSAGE){
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.chat_bubble_layout, parent, false);
}
else if(viewType==MY_IMAGE_MESSAGE){
//Image message
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.my_image_message_layout, parent, false);
}
else if(viewType==MY_VOICE_NOTE){
//Voice message
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.my_voice_message_layout, parent, false);
}
else if(viewType == OTHER_IMAGE_MESSAGE){
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.chatter_image_message_layout, parent, false);
}
else if(viewType==OTHER_VOICE_TYPE){
//Voice message
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.chatter_voice_message_layout, parent, false);
}
else{
view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.chatter_chat_bubble_layout, parent, false);
}
return new MessageViewHolder(view, mContext);
}
public void updateSent(boolean sent){
if(sent){
//Message is sent
}
else{
//error occured
}
}
@Override
public void onBindViewHolder(@NonNull final MessageViewHolder holder, int position) {
Message model = messages.get(position);
if(getItemViewType(position)==TOPIC_TYPE){
Log.d(TAG, "Topic Key:"+topicKey);
//Log.d(TAG, "message below topic: " + model.getText());
DatabaseReference topicRef = FirebaseDatabase.getInstance().getReference()
.child(FirebaseValues.TOPICS_TABLE).child(topicKey);
topicRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
final Topics topic = dataSnapshot.getValue(Topics.class);
TextView topicTv = holder.mView.findViewById(R.id.topicTextTv);
TextView usernameTv = holder.mView.findViewById(R.id.usernameTv);
TextView timeTv = holder.mView.findViewById(R.id.timestampTv);
CircleImageView userImage = holder.mView.findViewById(R.id.userImg);
if(topic!=null){
final TextView rateTv;
rateTv = holder.mView.findViewById(R.id.ratingTv);
final DatabaseReference ratingRef = FirebaseDatabase.getInstance().getReference()
.child(FirebaseValues.RATING_TABLE)
.child(topic.getUid());
ratingRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
Rating rating = dataSnapshot.getValue(Rating.class);
if(rating!=null){
ratingVal = rating.getTotal_rating();
noOfRates = rating.getNo_of_rates();
}
else{
ratingVal = 0;
}
rateTv.setText(String.format("%.1f", ratingVal/noOfRates)+"/5");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
rateTv.setTooltipText(String.format("%.1f", ratingVal/noOfRates)+" average rating from "+ noOfRates + "ratings");
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
Log.e(TAG, "Database Error: "+ databaseError.getMessage());
}
});
TextView rateUserTv;
rateUserTv = holder.mView.findViewById(R.id.rateUserTv);
rateUserTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//open rate user Dialog
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(mContext);
// ...Irrelevant code for customizing the buttons and title
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View dialogView = inflater.inflate(R.layout.rating_layout, null);
final SmileRating smileRating = dialogView.findViewById(R.id.smile_rating);
dialogBuilder.setView(dialogView);
final AlertDialog alertDialog = dialogBuilder.create();
Button submitBtn = dialogView.findViewById(R.id.submitRatingBtn);
submitBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
final int rating = smileRating.getRating();
if(ratingVal>=0){
noOfRates+=1;
float newRate = (ratingVal+rating);
Log.d(TAG, "New Rating: "+newRate);
Rating tempRate = new Rating(newRate, noOfRates);
ratingRef.setValue(tempRate).addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
DatabaseReference userRatingRef = FirebaseDatabase.getInstance().getReference()
.child(FirebaseValues.USER_TABLE)
.child(topic.getUid())
.child(FirebaseValues.RATING_TABLE)
.child(myUId);
userRatingRef.setValue(rating).addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
Toast.makeText(mContext, "Thanks for rating the conversation", Toast.LENGTH_SHORT).show();
alertDialog.dismiss();
}
});
}
});
}
}
});
alertDialog.show();
}
});
topicTv.setText(topic.getText());
String time = GetTimeAgo.getTimeAgo(topic.getTimestampCreatedLong(), mContext);
timeTv.setText(time);
if(!topic.isSecret()){
holder.setUserImage(topic.getUid(), userImage);
holder.setUsername(topic.getUid(), usernameTv);
}
else{
usernameTv.setText("Anonymous");
}
}
else{
topicTv.setText("Topic not found");
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
else if(getItemViewType(position)==MY_IMAGE_MESSAGE){
holder.setImageMessage(convId,messagesKey.get(position), model.getText());
}
else if(getItemViewType((position))==MY_VOICE_NOTE){
holder.setVoiceMessage(convId, messagesKey.get(position), model.getText());
}
else if( getItemViewType(position)==OTHER_IMAGE_MESSAGE){
//to replace sent to received
holder.setImageMessage(convId,messagesKey.get(position), model.getText().replace("Sent","Received"));
}
else if(getItemViewType(position)==OTHER_VOICE_TYPE){
holder.setVoiceMessage(convId, messagesKey.get(position), model.getText().replace("Sent","Received"));
}
else{
holder.setMessage(model.getText(), model.getFrom());
holder.mView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
PrettyDialog pd = new PrettyDialog(mContext);
pd.setTitle("Message Options");
pd.addButton(
"Delete Message", // button text
R.color.pdlg_color_white, // button text color
R.color.pdlg_color_red, // button background color
new PrettyDialogCallback() { // button OnClick listener
@Override
public void onClick() {
// Do what you gotta do
}
}
).addButton(
"Retract Message",
R.color.pdlg_color_white,
R.color.pdlg_color_red,
new PrettyDialogCallback() {
@Override
public void onClick() {
// Dismiss
}
}
).addButton(
"Copy", // button text
R.color.pdlg_color_white, // button text color
R.color.pdlg_color_green, // button background color
new PrettyDialogCallback() { // button OnClick listener
@Override
public void onClick() {
// Do what you gotta do
}
}
);
pd.show();
return true;
}
});
Log.d(TAG, "message: " + model.getText());
}
}
@Override
public int getItemCount() {
return messages.size();
}
@Override
public int getItemViewType(int position) {
if(position==0 && topicKey!=null){
//Insert the topic as first element
return TOPIC_TYPE;
}
Message message = messages.get(position);
if(message.getFrom().equals(myUId)){
//Message is mine
if(message.getType().equals(FirebaseValues.IMAGE_TYPE)){
return MY_IMAGE_MESSAGE;
}
else if(message.getType().equals(FirebaseValues.VOICE_NOTE_TYPE)){
return MY_VOICE_NOTE;
}
return MY_MESSAGE;
}
else{
//The message is from other user
if(message.getType().equals((FirebaseValues.IMAGE_TYPE))){
return OTHER_IMAGE_MESSAGE;
}
else if(message.getType().equals(FirebaseValues.VOICE_NOTE_TYPE)){
return OTHER_VOICE_TYPE;
}
}
return CONTENT;
}
由于stackoverflow的字数限制,我无法发布持有人类代码。
编辑: 我自己解决了此问题,方法是从回收者视图中删除该对象并再次添加它,然后他们在回收者视图上调用notifyItemInserted()。如果有人有更好的解决方案,请回答