Populating a Fragment with messages sent or received to other users using Cloud Firestore

Aaron Long :

I am currently in the process of making a chat for a renting mobile application. Currently I have linked my App with cloud Firestore and I am able to send and receive messages from different users once they have signed up !

My issue at the moment that I can't hack is that I am trying to populate this chatFragment.java class with the messages that the sender/Receiver has either sent or received. I believe I am on the right track but when I try to Query the snapshot it keeps saying that I need to declare it "Executor".

Any help would be great ! Cheers!

chatFragment.java

public class chatFragment extends Fragment {

    private FirebaseFirestore db = FirebaseFirestore.getInstance();
    private RecyclerView recyclerView;
    private userAdapter userAdapter;
    private List<User> mUsers;

    private FirebaseUser firebaseUser;
    private CollectionReference notebookRef ;

    private List<String> userList;

    public chatFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view =  inflater.inflate(R.layout.fragment_chat, container, false);


        recyclerView = view.findViewById(R.id.chat_view_recycler);
        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));


        firebaseUser = FirebaseAuth.getInstance().getCurrentUser();

        userList = new ArrayList<>();

        notebookRef = db.collection("Chats");



> notebookRef.addSnapshotListener( chatFragment.this, new EventListener<QuerySnapshot>() {
            @Override
            public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {

                userList.clear();
                if(!documentSnapshots.isEmpty())
                {
                    for(DocumentChange doc:documentSnapshots.getDocumentChanges())
                    {
                        Chat obj = doc.getDocument().toObject(Chat.class);

                        if(obj.getSender().equals(firebaseUser.getUid()))
                        {
                            userList.add(obj.getReceiver());
                        }
                        if(obj.getReceiver().equals(firebaseUser.getUid()))
                        {
                            userList.add(obj.getSender());
                        }

                    }

                    readChats();
                }
            }
        });

        return view;
    }

    private void readChats() {

        mUsers = new ArrayList<>();

        notebookRef = db.collection("Chats");

        notebookRef.addSnapshotListener((Executor) chatFragment.this, new EventListener<QuerySnapshot>() {
            @Override
            public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {

                userList.clear();


                for (DocumentChange doc : documentSnapshots.getDocumentChanges()) {
                    User obj = doc.getDocument().toObject(User.class);

                    for (String id : userList) {
                        if (obj.getUserName().equals(id)) {
                            if (mUsers.size() != 0) {
                                for (User userUI : mUsers) {
                                    if (!obj.getUserName().equals(userUI.getUserName())) {
                                        mUsers.add(obj);
                                    }
                                }
                            } else {
                                mUsers.add(obj);
                            }
                        }
                    }
                }

                Query query = notebookRef.orderBy("userId", Query.Direction.DESCENDING);
                FirestoreRecyclerOptions<User> options = new FirestoreRecyclerOptions.Builder<User>()
                        .setQuery(query, User.class)
                        .build();
                userAdapter = new userAdapter(options);
                recyclerView.setAdapter(userAdapter);
            }
        });

    }
}

MessageAdapter

public class userAdapter extends FirestoreRecyclerAdapter<User,userAdapter.UserViewHolder> {

    public userAdapter( FirestoreRecyclerOptions<User> options) {
        super(options);
    }

    @Override
    protected void onBindViewHolder(@NonNull UserViewHolder holder,final int position, @NonNull User model) {
        holder.list_studentNumber.setText(model.getStudentNumber());
        holder.list_userName.setText(model.getUserName());
        holder.list_admin.setText(String.valueOf(model.isAdmin()));
        Picasso.get().load(model.getPhotoUrl()).fit().centerCrop().into(holder.list_photo);
        Log.d("USERIDaaaaa", model.getUserName());

    }



    @NonNull
    @Override
    public UserViewHolder onCreateViewHolder( @NonNull ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.format_users_value, parent, false);
        return new UserViewHolder(v);
    }

    class UserViewHolder extends RecyclerView.ViewHolder {

        TextView list_admin;
        ImageView list_photo;
        TextView list_studentNumber;
        TextView list_userName;

        public UserViewHolder(final View itemView) {
            super(itemView);

            list_admin = itemView.findViewById(R.id.list_admin);
            list_photo = itemView.findViewById(R.id.list_photo);
            list_studentNumber = itemView.findViewById(R.id.list_studentNumber);
            list_userName = itemView.findViewById(R.id.list_userName);

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent intent = new Intent(itemView.getContext(), message_between_users.class);
                    itemView.getContext().startActivity(intent);
                }
            });
        }
    }
}

User.java


public class Chat implements Serializable {

        private String sender;
        private String receiver;
        private String message;
        private String Type;
        private Date Time;




    public Chat() {
            //empty constructor needed
        }

        public Chat(String sender, String receiver, String message, Date Time, String Type ) {
            this.sender = sender;
            this.receiver = receiver;
            this.message = message;
            this.Time = Time;
        }

        public String getSender() {
            return sender;
        }

        public void setSender(String sender) {
            this.sender = sender;
        }

        public String getReceiver() {
            return receiver;
        }

        public void setReceiver(String receiver) {
            this.receiver = receiver;
        }

        public String getType() { return Type; }

        public void setType(String type) { Type = type; }

        public Date getTime() { return Time; }

        public void setTime(Date time) { Time = time; }

        public String getMessage() {
            return message;
        }

        public void setMessage(String message) {
            this.message = message;
        }
    }

Error message at run time

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.clubapp, PID: 28835
    java.lang.ClassCastException: com.example.clubapp.chatFragment cannot be cast to java.util.concurrent.Executor
        at com.example.clubapp.chatFragment.onCreateView(chatFragment.java:65)
Frank van Puffelen :

There are three overloads of addSnapshotListener that take two arguments:

  1. addSnapshotListener(Activity activity, EventListener<QuerySnapshot> listener)
  2. addSnapshotListener(MetadataChanges metadataChanges, EventListener<QuerySnapshot> listener)
  3. addSnapshotListener(Executor executor, EventListener<QuerySnapshot> listener)

None of these overloads takes a Fragment as its first argument, so the compiler doesn't know what overload to call.

You're probably trying to call the first overload, so that the listener becomes scoped to the activity. But in that case you'll need to pass in the activity, and not the fragment.

It's actually an interesting idea to also allow scoping the listener to a fragment automatically, so you might want to file a feature request for that.


There's typically no need to pass an executor in for a listener, unless you have a need to control on what thread Firebase runs its network and disk I/O. In all other cases, attach you listeners like this:

notebookRef.addSnapshotListener(new EventListener<QuerySnapshot>() {
  ...

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=360980&siteId=1