geDemのアバターアイコン
geDem
 Blog
記事のカバー写真

Jetpack ComposeでFirestoreからデータを取得する方法

geDemのアバターアイコン
geDem
ペン

対象者:

  • すでに Firebase と Android の接続が完了している方

公式の手順通りに進めれば終わるはずです!!

Firestore にデータを入れる

まずは取得するためのデータを作っていきます。

Firebase のデータベース作成を選択したら、以下のような画面が出てくるので、データベース ID を入れて、「次へ」を押します。

(私は ID を「test」にしました。)

Firestoreでデータベース作成

次にルールを設定します。セキュリティみたいなものですね。

今回動かすのはサンプルなので、テストモードにしておきます。

Firestoreのデータベースルール設定

データベースが作成されます。

左側の「コレクションを追加」を押します。

コレクションは、テーブル的なものです。

Firestoreのからのデータベース画面

今回は、ユーザーデータを作成していきます。

なので、名前は「users」にします。

Firestoreでテーブル作成

コレクションができたら、データを入れていきましょう。

ドキュメントが1つのレコード(1 行分のデータ)になります。

今回は、name と age 属性を与えます。

ドキュメント ID は自動生成で大丈夫です。

Firestoreでデータ追加

3 つデータを入れてみました。

Firestoreにデータが入った様子

Jetpack ComposeFirestore からデータを取得する方法

まずは、gradle の設定からです。

build.gradle.kts(Module:App)

dependencies {
    // ...
    // Firestore
    implementation("com.google.firebase:firebase-firestore")
    // ViewModel
    implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1")
}

ui ディレクトリに新しく「TestViewModel.kt」ファイルを作成します。

TestViewModel.kt

class TestViewModel {
}

状態変数を設定します。

TestViewModel.kt

class TestViewModel : ViewModel() {
    private val _uiState = MutableStateFlow(listOf<User>())
    val uiState: StateFlow<List<User>> = _uiState.asStateFlow()
}

クラスの中に、データ取得のための関数を書いていきます。

TestViewModel.kt

// データ取得
private fun fetchUserData() {
    val db = Firebase.firestore
    db.collection("users")
        .get()
        .addOnSuccessListener { result ->
            for (document in result) {
                Log.d("SUCCESS", "${document.id} => ${document.data}")
            }
        }
        .addOnFailureListener { exception ->
            Log.w("FAILED", "Error getting documents.", exception)
        }
}

インスタンス化した時に動いて欲しいので、初期化処理の中に、先ほど書いた関数を入れます。

TestViewModel.kt

class testViewModel : ViewModel() {
    private val _uiState = MutableStateFlow(listOf<User>())
    val uiState: StateFlow<List<User>> = _uiState.asStateFlow()

    // 初期化
    init {
        fetchUserData()
    }

MainActivity の方に戻って、さきほどのクラスをインスタンス化してみて、ちゃんとデータが取得できるかみてみましょう。

MainActivity.kt

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
    val testViewModel: TestViewModel = viewModel()

    // ...
}

エミュレータを起動して実行します・・・

ちゃんと動いていそうですね!!

ログでFirestoreからデータを取得できたか確認する

次に、これらのデータを、UI に表示できる形にしたいです。

なので、まずは User のデータ型を宣言してあげます。

TestViewModel.kt

data class User(
    val id: String,
    val name: String,
    val age: Int?
)

class TestViewModel : ViewModel() {
    // ...

つぎに、fetchUserData 関数で、データが取得できた時の処理を変更します。

TestViewModel.kt

private fun fetchUserData() {
    // 取得したデータをまとめるためのリスト
    val users = mutableListOf<User>()

    val db = Firebase.firestore
    db.collection("users")
        .get()
        .addOnSuccessListener { result ->
            for (document in result) {
                // ユーザーデータ取得
                val userData = User(
                    id = document.id,
                    name = document.data["name"].toString(),
                    age = document.data["age"].toString().toInt(),
                )
                // 配列に代入
                users.add(userData)
            }
            // 状態を更新
            _uiState.update {
                users
            }
        }
        .addOnFailureListener { exception ->
            Log.w("FAILED", "Error getting documents.", exception)
        }
}

↑age のところ「.toString().toInt()」になっていて気持ち悪いです。。。

実力不足ですみません。。。


状態が更新されるようになったので、UI の方も変えていきましょう。

MainActivity.kt

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
    val testViewModel: TestViewModel = viewModel()
    val users by testViewModel.uiState.collectAsState()

    LazyColumn {
        item {
            users.map { user ->
                Row {
                    Text(text = user.name)
                    Text(text = user.age.toString())
                }
            }
        }
    }
}

これで表示されるはずです!

実行してみましょう。

Androidエミュレータの実行結果

表示できました!!やったー!!!🙌

参考

Firebase - Cloud Firestore を使ってみる

🙂‍↕️最後まで読んでいただきありがとうございます🙂‍↕️