Firestoreを使用したアプリをさくっと作ってみよう！！

#アプリケーションを作った動機
短期間でスマホのアプリケーションを作ってみようと思った。
Firestoreに興味があったので使ってみたかった。
単調ではあるが役にたつかもしれないものを作りたかった。
アウトプットをして自分の知識にしようと考えた。

##作ったアプリの概要
料理のレシピを登録できる。
今まで登録された料理のレシピをアプリを所持してる全ての人が観れる。

##Firebaseの導入
[Firebaseコンソール](https://firebase.google.com/)
こちらでプロジェクトを作り、指示に従って導入を行う。

プロジェクト内では
1.app直下にgoogle_service.jsonを配置

2.以下のコードを追加

```app/build.gradle
dependencies {
    ...
    //Firebase
    implementation 'com.google.firebase:firebase-analytics:17.0.1'
    implementation 'com.google.firebase:firebase-firestore:20.1.0'
    ...
}
apply plugin: 'com.google.gms.google-services'
```

```build.gradle
buildscript {
    repositories {
        google()
        jcenter()
        
    }
    dependencies {
        ...
        classpath 'com.google.gms:google-services:4.2.0'
    }
}
```

これでセットアップは完了です。

##Firestoreにデータを登録する処理
```RecipeInfo.java
    private String fireStoreCollectionPath = "recipes";
    private FirebaseFirestore fireStore = FirebaseFirestore.getInstance();

    private OnSuccessListener successListener = new OnSuccessListener<DocumentReference>() {
        @Override
        public void onSuccess(DocumentReference documentReference) {
            Log.d("success", "登録成功しました");
        }
    };
    private OnFailureListener onFailureListener = new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            Log.d("fail", "登録に失敗しました");
        }
    };

    /**
    * Firestoreにレシピを登録する処理
    * @param map Firestoreに登録されるレシピ情報
    */
    public void recipeAdd(Map map) {
        //firestoreのコレクション生成。
        fireStore.collection(fireStoreCollectionPath)
                .add(map)
                .addOnSuccessListener(successListener)
                .addOnFailureListener(onFailureListener);
    }
```

```RecipeAddActivity.java
    private Map<String, String> recipe = new HashMap<>();
    private EditText getRecipeTitle;
    private EditText getCooking;
    private EditText getIngredients;
    private String recipeTitle;
    private String cooking;
    private String ingredients;
    public Button addButton;
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recipe_add);

        recipeInfo = new RecipeInfo();
        getRecipeTitle = findViewById(R.id.recipe_title);
        getIngredients = findViewById(R.id.ingredients);
        getCooking = findViewById(R.id.cooking);
        addButton = findViewById(R.id.add_recipe);
        addButton.setOnClickListener(this);
    }

    /**
     * レシピ登録
     * */
    @Override
    public void onClick(View v) {
        try {
            //EditTextで入力された文字を文字列に格納
            recipeTitle = getRecipeTitle.getText().toString();
            ingredients = getIngredients.getText().toString();
            cooking = getCooking.getText().toString();
            
            //DBに登録する情報をmapに追加
            recipe.put("recipeTitle", recipeTitle);
            recipe.put("ingredients", ingredients);
            recipe.put("cooking", cooking);
            
            recipeInfo.recipeAdd(recipe);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
```
以上がボタン押下時に入力されたレシピがFirestoreに登録される処理になります。

##レシピの一覧を取得する処理

```GetRecipeList.java
    private String fireStoreCollectionPath = "recipes";
    private FirebaseFirestore fireStore = FirebaseFirestore.getInstance();
    private RecipeCallback mRecipeCallback;
    private ArrayList<Map> recipes = new ArrayList<>();

     /**
     * リスト取得
     * */
    private OnCompleteListener onCompleteListener = new OnCompleteListener<QuerySnapshot>() {
        @Override
        public void onComplete(@NonNull Task<QuerySnapshot> task) {
            if (task.isSuccessful()) {
                for (QueryDocumentSnapshot document : task.getResult()) {
                    recipes.add(document.getData());
                }
                mRecipeCallback.getRecipeMap(recipes);
            } else {
                mRecipeCallback.getRecipeMap(null);
            }
        }
    };

   /**
     * レシピの表示
     * */
    void recipeList(RecipeCallback recipeCallback) {
        mRecipeCallback = recipeCallback;
        fireStore.collection(fireStoreCollectionPath)
                .get()
                .addOnCompleteListener(onCompleteListener);
    }
```


```RecipeActivity.java
private Context mContext;
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_recipe);

        mContext = getApplicationContext();
        mRecipeCallback = new RecipeCallback() {
            @Override
            //Mapを返却するコールバック
            public void getRecipeMap(ArrayList<Map> recipes) {
                RecyclerView rv = (RecyclerView) findViewById(R.id.recyclerView);
                rv.setLayoutManager(new LinearLayoutManager(mContext));
                if (recipes == null) {
                    Log.d("fail", "読み込み失敗");
                    return;
                }
                final List<RecipeData> list = recipeListClass.createRecipeTitleList(recipes);
                
                //RecyclerView作成にリスト反映
                RecyclerViewAdapter adapter = new RecyclerViewAdapter(list);
                LinearLayoutManager llm = new LinearLayoutManager(mContext);
                rv.setHasFixedSize(true);
                rv.setLayoutManager(llm);
                rv.setAdapter(adapter);
                progressBar.setVisibility(ProgressBar.INVISIBLE);
                //項目タップ処理
                adapter.setOnItemClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        //材料、作り方の表示されるActivityに遷移
                    }
                });
            }
        };

        //レシピリスト呼び出し
        getRecipeList = new GetRecipeList();
        getRecipeList.recipeList();
    }
```
これでレシピのリストを取得することができます。
今回はFirestoreを中心に記事にしようと思ったのでRecyclerViewのadepterやViewHolderに関しては
機会がありましたら使用方法を別記事としてあげたいと思います。

##作成したアプリの画面
追加画面
<img width="300" alt="add.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164519/fa280e5f-1632-c58b-ef0b-c5c41ce2439b.jpeg">
一覧画面
<img width="300" alt="list.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164519/558ca546-77b7-fc07-65ca-a2b78994cc14.jpeg">
リストタップ処理後
<img width="300" alt="cooking.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164519/36a4e3ce-2539-e491-cbab-b8bdf98bfd2a.jpeg">

##作ってみた感想
Firestore便利すぎるし、実装が予想以上に簡単だった。
どちらかというと、自分のデザインセンスのなさに苦戦しました。
非同期処理も今回使用したFirestoreのメソッドが行ってくれているため、こちらからする必要はない。

結論：Firebaseは最高です。