使用来自firebase

时间:2018-02-05 20:02:22

标签: android firebase firebase-realtime-database

我正在使用firebase开发基本聊天应用程序。我能够存储和检索来自firebase的数据/消息!但是当我滚动聊天(Recyclerview)时,一些消息暂时不会显示/消失。

这样的事情: Losing chat messages

当我回到userlist_activity,然后再次访问chat_activity时,它会显示所有消息。但是,如果我再次滚动聊天,一些消息就会消失,直到我回去再来。我已多次检查我的firebase数据库,看看我是否错过了这些消息。但不,数据库中存在所有消息。但仍然没有从聊天窗口消失!

这是我的MainActivity / ChatAcitivty:

public class MainActivity extends AppCompatActivity {

private static final String TAG = "MainActivity";

public static final String ANONYMOUS = "anonymous";
public static final int DEFAULT_MSG_LENGTH_LIMIT = 1000;
private static final int RC_SIGN_IN = 1;

private RecyclerView mMessageRecyclerView;
private MessageAdapter mMessageAdapter;
private ProgressBar mProgressBar;
private ImageButton mPhotoPickerButton;
private EditText mMessageEditText;
private Button mSendButton;

private String mUsername;
private String mUserId;
private String friendUserID;
private ArrayList<ChatMessage> friendlyMessages;
private ArrayList<ChatMessage> selectedItems = new ArrayList<>();
private boolean multiSelect = false;
private int mPosition;

private FirebaseDatabase mFirebaseDatabase;     //Entry Point to the database
private DatabaseReference mMessageDatabaseReference;   //Reference to the specific part of the database.
private ChildEventListener mChildEventListener;
private FirebaseAuth mFirebaseAuth;
private FirebaseAuth.AuthStateListener mAuthStateListener;


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

    mUsername = ANONYMOUS;
    mFirebaseDatabase = FirebaseDatabase.getInstance();
    mFirebaseAuth = FirebaseAuth.getInstance();

    friendUserID = getIntent().getStringExtra("clickedUserID");
    setTitle(getIntent().getStringExtra("clickedUsername"));
    SendBird.setFriendUserID(friendUserID);

    mMessageDatabaseReference = mFirebaseDatabase.getReference().child("message");
    mMessageDatabaseReference.keepSynced(true);

    // Initialize references to views
    mProgressBar = findViewById(R.id.progressBar);
    mMessageRecyclerView = findViewById(R.id.recycler_view_message);
    mPhotoPickerButton = findViewById(R.id.photoPickerButton);
    mMessageEditText = findViewById(R.id.messageEditText);
    mSendButton = findViewById(R.id.sendButton);

    // Initialize message RecyclerView and its adapter
    friendlyMessages = new ArrayList<>();
    mMessageAdapter = new MessageAdapter(friendlyMessages, this);
    mMessageRecyclerView.setHasFixedSize(true);
    RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(this);
    mMessageRecyclerView.setLayoutManager(mLayoutManager);
    mMessageRecyclerView.setAdapter(mMessageAdapter);

    // Initialize progress bar
    mProgressBar.setVisibility(ProgressBar.INVISIBLE);

    // ImagePickerButton shows an image picker to upload a image for a message
    mPhotoPickerButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            // TODO: Fire an intent to show an image picker
        }
    });

    mMessageEditText.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
            if (charSequence.toString().trim().length() > 0) {
                mSendButton.setEnabled(true);
            } else {
                mSendButton.setEnabled(false);
            }
        }

        @Override
        public void afterTextChanged(Editable editable) {
        }
    });
    mMessageEditText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(DEFAULT_MSG_LENGTH_LIMIT)});

    mSendButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            ChatMessage chatMessage = new ChatMessage(mUsername, null, mMessageEditText.getText().toString(),
                    System.currentTimeMillis(), mUserId, friendUserID);
            mMessageDatabaseReference.push().setValue(chatMessage);
            // Clear input box
            mMessageEditText.setText("");
        }
    });

    mAuthStateListener = new FirebaseAuth.AuthStateListener() {
        @Override
        public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {

            FirebaseUser user = firebaseAuth.getCurrentUser();
            if (user != null) {
                onSignedInInitialize(user.getDisplayName(), user.getUid());
            } else {
                onSignedOutCleanup();
            }
        }
    };
}

private void onSignedOutCleanup() {
    mUsername = ANONYMOUS;
    clear();
    detachDatabaseReadListener();
}

private void onSignedInInitialize(String userName, String userId) {
    mUsername = userName;
    mUserId = userId;
    attachDatabaseReadListener();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.main_menu, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.sign_out_menu:
            AuthUI.getInstance().signOut(this);
            return true;

        default:
            return super.onOptionsItemSelected(item);
    }

}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == RC_SIGN_IN) {
        if (resultCode == RESULT_OK) {
            Toast.makeText(this, "Signed in!", Toast.LENGTH_SHORT).show();
        } else if (resultCode == RESULT_CANCELED) {
            Toast.makeText(this, "Sign in canceled!", Toast.LENGTH_SHORT).show();
            finish();
        }
    }
}

@Override
protected void onResume() {
    super.onResume();
    mFirebaseAuth.addAuthStateListener(mAuthStateListener);

    attachDatabaseReadListener();
}

@Override
protected void onPause() {
    super.onPause();
    if (mAuthStateListener != null) {
        mFirebaseAuth.removeAuthStateListener(mAuthStateListener);
    }
    detachDatabaseReadListener();
    clear();
}

private void attachDatabaseReadListener() {
    if (mChildEventListener == null) {
        mChildEventListener = new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                ChatMessage chatMessage = dataSnapshot.getValue(ChatMessage.class);
                friendlyMessages.add(chatMessage);
              //mMessageAdapter.notifyItemInserted(friendlyMessages.size() - 1);
                mMessageAdapter.notifyDataSetChanged();
                mMessageRecyclerView.smoothScrollToPosition(friendlyMessages.size() - 1);
            }

            @Override
            public void onChildChanged(DataSnapshot dataSnapshot, String s) {
            }

            @Override
            public void onChildRemoved(DataSnapshot dataSnapshot) {
            }

            @Override
            public void onChildMoved(DataSnapshot dataSnapshot, String s) {
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
            }
        };
        mMessageDatabaseReference.addChildEventListener(mChildEventListener);
    }
}

private void detachDatabaseReadListener() {
    if (mChildEventListener != null) {
        mMessageDatabaseReference.removeEventListener(mChildEventListener);
        mChildEventListener = null;
    }
}

public void clear() {
    int size = this.friendlyMessages.size();
    friendlyMessages.clear();
    mMessageAdapter.notifyItemRangeRemoved(0, size);
   }
}

这是我的MessageAdapter:

public class MessageAdapter extends RecyclerView.Adapter {

private static final int VIEW_TYPE_MESSAGE_SENT = 1;
private static final int VIEW_TYPE_MESSAGE_RECEIVED = 2;

private ArrayList<ChatMessage> chatList;
private Context mContext;


public MessageAdapter(ArrayList<ChatMessage> chatList, Context mContext) {
    this.chatList = chatList;
    this.mContext = mContext;
}

@Override
public int getItemViewType(int position) {
    ChatMessage chatMessage = chatList.get(position);

    if (chatMessage.getUserId().equals(SendBird.getCurrnetUserId())) {
        // If the current user is the sender of the message
        Log.d("Adapter", "type message sent");
        return VIEW_TYPE_MESSAGE_SENT;
    } else {
        // If some other user sent the message
        return VIEW_TYPE_MESSAGE_RECEIVED;
    }

}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view;
    if (viewType == VIEW_TYPE_MESSAGE_SENT) {
        view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_message_sent, parent, false);
        Log.d("Adapter", "create message sent");
        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;
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    ChatMessage message = chatList.get(position);

    switch (holder.getItemViewType()) {
        case VIEW_TYPE_MESSAGE_SENT:
            ((SentMessageHolder) holder).bind(message);
            Log.d("Adapter", "bind message sent");
            break;
        case VIEW_TYPE_MESSAGE_RECEIVED:
            ((ReceivedMessageHolder) holder).bind(message);
    }
}

@Override
public int getItemCount() {
    return chatList.size();
}

private class SentMessageHolder extends RecyclerView.ViewHolder {
    TextView messageTextView;
    TextView authorTextView;
    TextView mTimeTextView;
    ImageView photoImageView;

    public SentMessageHolder(View itemView) {
        super(itemView);
        messageTextView = itemView.findViewById(R.id.messageTextView);
        authorTextView = itemView.findViewById(R.id.nameTextView);
        photoImageView = itemView.findViewById(R.id.photoImageView);
        mTimeTextView = itemView.findViewById(R.id.timeTextView);
    }

    void bind(ChatMessage message) {
        String to = message.getzFriendUserId();

        if (to.equals(SendBird.getFriendUserID())) {
            messageTextView.setText(message.getText());
            authorTextView.setText("You");
            // Format the stored timestamp into a readable String using method.
            mTimeTextView.setText(Utils.formatDateTime(message.getTime()));
        } else {
            itemView.setVisibility(View.GONE);
        }

    }
}

private class ReceivedMessageHolder extends RecyclerView.ViewHolder {
    TextView messageTextView;
    TextView authorTextView;
    TextView mTimeTextView;
    ImageView photoImageView;

    ReceivedMessageHolder(View itemView) {
        super(itemView);
        messageTextView = itemView.findViewById(R.id.messageTextView);
        authorTextView = itemView.findViewById(R.id.nameTextView);
        photoImageView = itemView.findViewById(R.id.photoImageView);
        mTimeTextView = itemView.findViewById(R.id.timeTextView);
    }

    void bind(ChatMessage message) {
        String friendUserId = message.getzFriendUserId();
        String sendId = message.getUserId();
        if (friendUserId.equals(SendBird.getCurrnetUserId()) && SendBird.getFriendUserID().equals(sendId)) {
            messageTextView.setText(message.getText());
            authorTextView.setText(message.getName());
            // Format the stored timestamp into a readable String using method.
            mTimeTextView.setText(Utils.formatDateTime(message.getTime()));
        } else {
            itemView.setVisibility(View.GONE);
        }
    }
  }

}

我认为它与firebase同步相关,但我不确定究竟是什么造成了这个问题。任何建议/答案都会非常有用!

更新

item_message_received.xml

<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:background="@drawable/rounded_rectangle_white"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<TextView
    android:id="@+id/messageTextView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="8dp"
    android:textAppearance="?android:attr/textAppearanceLarge"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    tools:text="Message" />

<TextView
    android:id="@+id/nameTextView"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginBottom="8dp"
    android:textAppearance="?android:attr/textAppearanceSmall"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toStartOf="@+id/timeTextView"
    app:layout_constraintStart_toStartOf="@+id/messageTextView"
    app:layout_constraintTop_toBottomOf="@+id/messageTextView"
    tools:text="Name" />

<TextView
    android:id="@+id/timeTextView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginEnd="8dp"
    android:layout_marginRight="8dp"
    android:textAppearance="?android:attr/textAppearanceSmall"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toEndOf="@+id/messageTextView"
    app:layout_constraintTop_toBottomOf="@+id/messageTextView"
    tools:text="2:35PM" />

<ImageView
    android:id="@+id/photoImageView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"/>

</android.support.constraint.ConstraintLayout>

item_message_sent.xml:

<android.support.constraint.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="wrap_content"
android:layout_marginBottom="4dp"
android:background="#E0E0E0">

<android.support.constraint.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:id="@+id/constraint2"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_marginBottom="4dp"
    android:background="@drawable/rounded_rectangle_white"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent">

    <TextView
        android:id="@+id/messageTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:textAppearance="?android:attr/textAppearanceLarge"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/constraint2"
        tools:text="Message" />

    <TextView
        android:id="@+id/nameTextView"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="4dp"
        android:textAppearance="?android:attr/textAppearanceSmall"
        app:layout_constraintBottom_toBottomOf="@+id/constraint2"
        app:layout_constraintEnd_toStartOf="@+id/timeTextView"
        app:layout_constraintStart_toStartOf="@+id/messageTextView"
        app:layout_constraintTop_toBottomOf="@+id/messageTextView"
        tools:text="Name" />

    <TextView
        android:id="@+id/timeTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:textAppearance="?android:attr/textAppearanceSmall"
        app:layout_constraintEnd_toEndOf="@+id/constraint2"
        app:layout_constraintStart_toEndOf="@+id/messageTextView"
        app:layout_constraintTop_toBottomOf="@+id/messageTextView"
        tools:text="2:35PM" />

    <ImageView
        android:id="@+id/photoImageView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>

0 个答案:

没有答案