FirestoreのデータをRecyclerViewで表示する[Java]


Firestoreのデータが更新されるたびにRecyclerViewの表示も更新されるようなことをやりたかったのですが、日本語で書かれた記事が全然なくて苦戦しました。

この記事ではFirebaseUI for Cloud Firestoreを参考にFirestoreRecyclerAdapterを使ってチャットアプリを作ってみます。

Firestoreでのデータベース作成がまだの人はCloud Firestore を使ってみるを参照してみてください。

表示するデータのモデル

チャットアプリのチャットを構成するデータのモデルです。

Chat.java
public class Chat {
    private String mName;
    private String mMessage;
    private String mUid;
    private Date mTimestamp;

    public Chat() { } // Needed for Firebase

    public Chat(String name, String message, String uid) {
        mName = name;
        mMessage = message;
        mUid = uid;
    }

    public String getName() { return mName; }

    public void setName(String name) { mName = name; }

    public String getMessage() { return mMessage; }

    public void setMessage(String message) { mMessage = message; }

    public String getUid() { return mUid; }

    public void setUid(String uid) { mUid = uid; }

    @ServerTimestamp
    public Date getTimestamp() { return mTimestamp; }

    public void setTimestamp(Date timestamp) { mTimestamp = timestamp; }
}

Firebase UIの準備

まず、FirebaseUI for Cloud Firestoreをインポートします。
FirestoreRecyclerAdapterを使うためです。

app/build.gradle
implementation "com.firebaseui:firebase-ui-firestore:6.2.1"

Queryの作成

"chats"コレクションのqueryを作成します。

MainActivity.java
Query query = FirebaseFirestore.getInstance()
        .collection("chats")
        .orderBy("timestamp")
        .limit(50); //最新の50個を取得

Queryのセット

先ほど作成したqueryを入れていきます。
Chat.classのところには自分で用意したモデルのクラスを入れてください。

MainActivity.java
FirestoreRecyclerOptions<Chat> options = new FirestoreRecyclerOptions.Builder<Chat>()
        .setQuery(query, Chat.class)
        .build();

上のコードではクエリーで取得したデータを自動的に"Chatクラス"に入れてくれますが、何らかの理由で自分で入れたい人は以下のようにしてください。

MainActivity.java

FirestoreRecyclerOptions<Chat> options = new FirestoreRecyclerOptions.Builder<Chat>()
        .setQuery(query, new SnapshotParser<Chat>() {
        @Override
        public Chat parseSnapshot(@NonNull DocumentSnapshot snapshot) {
            /* スナップショットの取得時に行いたい処理を書く */
            name = snapshot.getString("mName");
            message = snapshot.getString("mMessage");
            uid = snapshot.getString("mUid");
            Chat chat = new Chat(name,message,uid);
            return chat;
       }
       })
      .build();

ViewHolderの作成

RecyclerView.ViewHolderを継承したクラスを作成します。

ChatHolder.java
public class ChatHolder extends RecyclerView.ViewHolder {

    public TextView messsageText;
    public TextView nameText;

    public ChatHolder(View itemView) {
        super(itemView);
        messsageText = itemView.findViewById(R.id.message_text);
        nameText = itemView.findViewById(R.id.name_text);
    }

   public void setMessage(String message){
       messsageText.setText(message);
   }

   public void setName(String name){
       nameText.setText(name);
   }
}

アダプターを作成

アダプターはFirestoreRecyclerAdapterを継承して作成します。

MainActivity.java
FirestoreRecyclerAdapter adapter = new FirestoreRecyclerAdapter<Chat, ChatHolder>(options) {
    @Override
    public void onBindViewHolder(ChatHolder holder, int position, Chat model) 
    {
        // ChatHolderにChatクラスのオブジェクトを入れていきます
        holder.setMessage(model.getMessage());
        holder.setName(model.getName());
    }

    @Override
    public ChatHolder onCreateViewHolder(ViewGroup group, int i) {
        // ここではViewHolderのインスタンスを作成します
        View view = LayoutInflater.from(group.getContext())
                .inflate(R.layout.message, group, false);

        return new ChatHolder(view);
    }
};

【忘れずに】リスナーの登録

リスナーをつけないと動きません。僕はここで少しハマりました。。。

MainActivity.java
@Override
protected void onStart() {
    super.onStart();
    adapter.startListening();
}

@Override
protected void onStop() {
    super.onStop();
    adapter.stopListening();
}

以上で完了です!お疲れさまでした!

おわりに

これで行けるはずです!
間違ってる箇所、不明な点があれば教えてください!
Android開発がんばっていきましょう!
よかったらLGTMお願いします。

参考