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

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

この記事では[FirebaseUI for Cloud Firestore](https://github.com/firebase/FirebaseUI-Android/tree/master/firestore#using-the-firestorepagingadapter)を参考に**FirestoreRecyclerAdapter**を使ってチャットアプリを作ってみます。

Firestoreでのデータベース作成がまだの人は[Cloud Firestore を使ってみる](https://firebase.google.com/docs/firestore/quickstart?hl=ja)を参照してみてください。


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




```java: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を作成します。

```java:MainActivity.java
Query query = FirebaseFirestore.getInstance()
        .collection("chats")
        .orderBy("timestamp")
        .limit(50); //最新の50個を取得
```
#
#Queryのセット
先ほど作成したqueryを入れていきます。
Chat.classのところには自分で用意したモデルのクラスを入れてください。

```java:MainActivity.java
FirestoreRecyclerOptions<Chat> options = new FirestoreRecyclerOptions.Builder<Chat>()
        .setQuery(query, Chat.class)
        .build();
```
上のコードではクエリーで取得したデータを自動的に"Chatクラス"に入れてくれますが、何らかの理由で自分で入れたい人は以下のようにしてください。


```java: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を継承したクラスを作成します。

```java: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を継承して作成します。

```java: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);
    }
};
```
#【忘れずに】リスナーの登録
リスナーをつけないと動きません。僕はここで少しハマりました。。。

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

@Override
protected void onStop() {
    super.onStop();
    adapter.stopListening();
}
```
以上で完了です！お疲れさまでした！

#おわりに

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

#参考
- [FirebaseUI for Cloud Firestore](https://github.com/firebase/FirebaseUI-Android/tree/master/firestore#using-the-firestorepagingadapter)
- [Firestoreからデータを取得してRecyclerViewに表示［Kotlin］](https://qiita.com/Dean/items/542d3dda6cb660244d4e)