FirebaseRecyclerAdapter在回收视图中复制对象

时间:2018-12-17 21:38:09

标签: android firebase firebase-realtime-database android-recyclerview recycler-adapter

我的结构: My Structure

我正在使用Firebase实时数据库开发聊天应用程序。我正在使用FirebaseRecyclerAdapter来显示消息。但是问题在于滚动,消息被复制并且混乱。

这是我的实现:

public class FirebaseChatActivity extends AppCompatActivity {


private String messageSenderId;
private String messageReceiverId;

private FirebaseRecyclerAdapter<ChatMessage, MessageViewHolder> firebaseRecyclerAdapter;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_firebase_chat);

    RecyclerView recyclerView = findViewById(R.id.rv_firebase_chat_activity);
    recyclerView.setLayoutManager(new LinearLayoutManager(this));


    messageSenderId = "eoSU5m7PyucyC9h30JfHhV6S8Av2";
    messageReceiverId = "ZOqofCid0XN5ovIAj1mXhRYxdnO2";

    DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
    Query query = rootRef.child("messages").child(messageSenderId).child(messageReceiverId);


    FirebaseRecyclerOptions<ChatMessage> firebaseRecyclerOptions = new FirebaseRecyclerOptions.Builder<ChatMessage>()
            .setQuery(query, ChatMessage.class)
            .build();


    firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<ChatMessage, MessageViewHolder>(firebaseRecyclerOptions) {
        @Override
        protected void onBindViewHolder(@NonNull MessageViewHolder messageViewHolder, int position, @NonNull ChatMessage message) {


            if (message.getMessageType().equals("text")) {
                messageViewHolder.showMessage.setText(message.getMessageText());
            } else if (message.getMessageType().equals("image")) {

                try {
                    Glide.with(getApplicationContext())
                            .load(message.getPhotoUrl())
                            .placeholder(R.drawable.no_image2)
                            .error(R.drawable.image_1)
                            .into(messageViewHolder.photoImageView);
                } catch (Exception e) {
                    Log.d("MessageAdapterLog", e.toString());
                }

            }

        }

        @Override
        public MessageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {


            android.view.View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_item_right, parent, false);
            return new MessageViewHolder(view);


        }
    };
    recyclerView.setAdapter(firebaseRecyclerAdapter);
}


private class MessageViewHolder extends RecyclerView.ViewHolder {


    public TextView showMessage;
    public ImageView photoImageView;

    public MessageViewHolder(@NonNull android.view.View itemView) {
        super(itemView);

        showMessage = itemView.findViewById(R.id.show_message);
        photoImageView = itemView.findViewById(R.id.photo_image_view);
    }

}


@Override
protected void onStart() {
    super.onStart();
    firebaseRecyclerAdapter.startListening();
}

@Override
protected void onStop() {
    super.onStop();

    if (firebaseRecyclerAdapter!= null) {
        firebaseRecyclerAdapter.stopListening();
    }
}
}

我尝试了许多不同的解决方案,例如设置为here .addChildEventListener (完全不同的实现),但无法解决问题。

完整活动代码以及数据库结构已附加。请让我知道我在做什么错。

谢谢

1 个答案:

答案 0 :(得分:2)

问题在于,每次滚动时,要使新项目再次可见,它将在onBindViewHolder中运行代码以使该视图膨胀并重新绑定。

if (message.getMessageType().equals("text")) {
                messageViewHolder.showMessage.setText(message.getMessageText());
            } else if (message.getMessageType().equals("image")) {

                try {
                    Glide.with(getApplicationContext())
                            .load(message.getPhotoUrl())
                            .placeholder(R.drawable.no_image2)
                            .error(R.drawable.image_1)
                            .into(messageViewHolder.photoImageView);
                } catch (Exception e) {
                    Log.d("MessageAdapterLog", e.toString());
                }

            }

        }

要解决此问题,您将需要重写适配器中的两个方法

@Override
public long getItemId(int position) {
    return position;
}

@Override
public int getItemViewType(int position) {
   return position;
}