Skip to main content

[Make-A] Simple Chat Application using Cloud Firestore Part 7 – Displaying The Chat Rooms

As a user,
I want to see all the rooms available,
So that I can choose which room to go to
  • Display rooms in alphabetical order
  • Clicking on a chat room opens that chat room

Table of Contents

  1. Part 1 – Specs and Introduction
  2. Part 2 – Setting up Firebase Cloud Firestore
  3. Part 3 – Adding a Simple Authentication
  4. Part 4 – Adding a FloatingActionButton (FAB)
  5. Part 5 – Creating a Chat Room
  6. Part 6 – Entering The Chat Room
  7. Part 7 – Displaying The Chat Rooms
  8. Part 8 – Chat
  9. 10 Exercises and Thanks!

 

1. ChatRoom POJO

1. Create a new class called ChatRoom

2. Declare two fields: id and name

public class ChatRoom {

    private String id;
    private String name;

    public ChatRoom(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

 

2. Setting up our RecyclerView.Adapter

1. Create a new layout called item_chat_room.xml

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/item_chat_room_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium"
        android:padding="8dp"/>

</LinearLayout>

2. Create a new class called ChatRoomsAdapter

public class ChatRoomsAdapter extends RecyclerView.Adapter<ChatRoomsAdapter.ChatRoomViewHolder> {

    private List<ChatRoom> chatRooms;

    public ChatRoomsAdapter(List<ChatRoom> chatRooms) {
        this.chatRooms = chatRooms;
    }

    @Override
    public ChatRoomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(
                R.layout.item_chat_room,
                parent,
                false
        );
        return new ChatRoomViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ChatRoomViewHolder holder, int position) {
        holder.bind(chatRooms.get(position));
    }

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

    class ChatRoomViewHolder extends RecyclerView.ViewHolder {
        TextView name;
        ChatRoom chatRoom;

        public ChatRoomViewHolder(View itemView) {
            super(itemView);
            name = itemView.findViewById(R.id.item_chat_room_name);
        }

        public void bind(ChatRoom chatRoom) {
            this.chatRoom = chatRoom;
            name.setText(chatRoom.getName());
        }
    }
}
  • ChatRoomViewHolder.bind(…) – helper method that we use to populate the Views of the ViewHolder and keep track on what ChatRoom this ViewHolder is currently holding so that when we handle clicks later in this tutorial we know what ChatRoom is clicked.

Now that we have our adapter set up, let’s populate this adapter with chat rooms saved in Cloud Firestore.

 

3. Fetch and display chat rooms in Cloud Firestore

1. Open your ChatRoomRepository.class

2. Create a new method called getRooms()

public class ChatRoomRepository {
    private static final String TAG = "ChatRoomRepo";

    private FirebaseFirestore db;

    public ChatRoomRepository(FirebaseFirestore db) {
        this.db = db;
    }

    ...

    public void getRooms(EventListener<QuerySnapshot> listener) {
        db.collection("rooms")
                .orderBy("name")
                .addSnapshotListener(listener);
    }
}

3. Open your MainActivity.class and initialize our RecyclerView and ChatRoomRepository

public class MainActivity extends AppCompatActivity {

    ...
    ChatRoomRepository chatRoomRepository;

    ...
    private RecyclerView chatRooms;
    private ChatRoomsAdapter adapter;

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

        ...
        chatRoomRepository = new ChatRoomRepository(FirebaseFirestore.getInstance());

        ...

        initUI();

        ...
    }

    private void initUI() {
        chatRooms = findViewById(R.id.rooms);
        chatRooms.setLayoutManager(new LinearLayoutManager(this));

        ...
    }

    ...
}

4. In your MainActivity.class, create a new method called getChatRooms() and call it after initUI()

public class MainActivity extends AppCompatActivity {

    ...

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

        ...

        initUI();

        getChatRooms();

        ...
    }

    ...

    private void getChatRooms() {
        chatRoomRepository.getRooms(new EventListener<QuerySnapshot>() {
            @Override
            public void onEvent(QuerySnapshot snapshots, FirebaseFirestoreException e) {
                if (e != null) {
                    Log.e("MainActivity", "Listen failed.", e);
                    return;
                }

                List<ChatRoom> rooms = new ArrayList<>();
                for (QueryDocumentSnapshot doc : snapshots) {
                    rooms.add(new ChatRoom(doc.getId(), doc.getString("name")));
                }

                adapter = new ChatRoomsAdapter(rooms);
                chatRooms.setAdapter(adapter);
            }
        });
    }

    ...
}

5. Launch the app and you should see all the chat rooms that you’ve created in Cloud Firestore! 🎉🎉🎉

When you click a chat room, nothing happens. Let’s handle clicks and start our ChatRoomActivity.class.

 

4. Clicking on a chat room opens the chat room

1. Open your ChatRoomsAdapter.class

2. Declare an interface called OnChatRoomClickListener

3. Pass it in your ChatRoomAdapter’s constructor

public class ChatRoomsAdapter extends RecyclerView.Adapter<ChatRoomsAdapter.ChatRoomViewHolder> {

    interface OnChatRoomClickListener {
        void onClick(ChatRoom chatRoom);
    }

    ...
    private OnChatRoomClickListener listener;

    public ChatRoomsAdapter(List<ChatRoom> chatRooms, OnChatRoomClickListener listener) {
        this.chatRooms = chatRooms;
        this.listener = listener;
    }

    ...
}

4. In your ChatRoomViewHolder.class, use the listener that we received in ChatRoomAdapter’s constructor

class ChatRoomViewHolder extends RecyclerView.ViewHolder {
    TextView name;
    ChatRoom chatRoom;

    public ChatRoomViewHolder(View itemView) {
        super(itemView);
        name = itemView.findViewById(R.id.item_chat_room_name);
        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                listener.onClick(chatRoom);
            }
        });
    }

    ...
}

5. Back to our MainActivity.class, let’s create an OnChatRoomClickListener and pass it in your ChatRoomAdapter’s constructor

public class MainActivity extends AppCompatActivity {

    ...

    private void getChatRooms() {
        chatRoomRepository.getRooms(new EventListener<QuerySnapshot>() {
            @Override
            public void onEvent(QuerySnapshot snapshots, FirebaseFirestoreException e) {
                if (e != null) {
                    Log.e("MainActivity", "Listen failed.", e);
                    return;
                }

                List<ChatRoom> rooms = new ArrayList<>();
                for (QueryDocumentSnapshot doc : snapshots) {
                    rooms.add(new ChatRoom(doc.getId(), doc.getString("name")));
                }

                adapter = new ChatRoomsAdapter(rooms, listener);
                chatRooms.setAdapter(adapter);
            }
        });
    }

    ChatRoomsAdapter.OnChatRoomClickListener listener = new ChatRoomsAdapter.OnChatRoomClickListener() {
        @Override
        public void onClick(ChatRoom chatRoom) {
            Intent intent = new Intent(MainActivity.this, ChatRoomActivity.class);
            intent.putExtra(ChatRoomActivity.CHAT_ROOM_ID, chatRoom.getId());
            intent.putExtra(ChatRoomActivity.CHAT_ROOM_NAME, chatRoom.getName());
            startActivity(intent);
        }
    };

    ...
}

6. Launch the app and when you click a chat room it opens that chat room!!! 🎉🎉🎉

 

5. Review

As a user,
I want to see all the rooms available,
So that I can choose which room to go to
  • Display rooms in alphabetical order
  • Clicking on a chat room opens that chat room

✓ Display rooms in alphabetical order
 Clicking on a chat room opens that chat room

A chat room without messages is pretty useless right? 😂 Let’s now implement the chat feature for our app the last part of the tutorial. We’re almost done! Wohoo! 🎉