如何使用Kotlin在安卓系统中整合云端Firestore数据库

338 阅读6分钟

使用Kotlin在安卓系统中整合云端Firestore数据库

Firestore是一个云托管的NoSQL数据库,可以通过各自的SDK集成到各种平台(iOS、Android和Web应用)。

它是一个可靠的数据库,因为它提供了灵活的数据存储结构、表达式查询、离线缓存支持、改进的身份和访问管理(IAM)以及同步的实时更新。

现代应用程序有望顺利运行,并提供尽可能好的用户体验,这正是Firestore带给我们的东西。在这篇文章中,我们将学习如何在使用Kotlin编程语言的Android应用中使用Firestore。

Firestore如何存储数据

与其他流行的数据库不同,Firestore以NoSQL格式存储数据,也就是说,数据被存储在节点内的JSON对象中。这些节点被称为文档。一个文档不能单独存在。必须有一个持有至少一个文档的父容器。这个容器被称为一个集合。

随着数据库的增长,一个树状结构就形成了,相关的文档和集合借助各自的IDs ,连接到一个共同的集合。Firestore的独特之处在于,它支持在文档内部创建集合。这些埋藏的集合被称为子集合。

例如,为了创建一个users 数据库,我们将创建一个叫做users 的集合,并添加具有unique ID的文档,每个文档都持有用户的属性。这些属性可以是以下数据类型。

布尔值、数字、字符串、地理点、二进制blob、Cloud Firestore引用、数组、地图值和时间戳。

创建一个Firebase项目

Cloud Firestore是Firebase提供的产品之一。因此,我们需要创建一个Firebase项目,在这个项目中我们将创建数据库。进入Firebase官方网站,用你的谷歌账户登录。

点击Go to console ,然后点击+ add project 。这将启动一个3步程序,要求你为你的项目设置名称、项目ID、位置,最后接受服务条款。

Firebase project example

创建一个安卓项目

现在,让我们继续创建一个Android项目,稍后我们将把它与我们刚刚创建的Firebase项目连接起来。启动你的IDE,开始一个你选择的新项目。

连接这两个项目

到目前为止,我们已经创建了两个不同的项目,但它们都需要彼此来实现其目的。为了连接Android和Firebase项目,你需要做以下工作。

从Firebase控制台下载项目的配置文件

配置文件是一个JSON ,通常命名为google-services.json ,包含了所有连接到Firebase项目的应用程序的信息。

打开Firebase控制台,点击你想连接到你的应用程序的项目。就在项目名称的下面是一个可用平台的列表,你可以使用。点击Android的标志来继续。

1.添加应用程序的详细信息

这是最关键的一步,因为它直接对配置文件产生影响。复制并粘贴软件包的名称,以避免输入错误。这可以位于模块级build.gradle 文件中。

Add app details

2.下载配置文件

注册完应用程序后,点击Download google.services.json ,获得你的配置文件。

Download config file

回到Android Studio,切换到Project view 。这将显示你项目中的所有文件和目录。将配置文件粘贴到app 文件夹中,并进行同步。

将Firebase SDK加载到我们的应用程序中

Firebase SDK允许我们访问诸如Firebase auth、实时数据库、Firebase ML、Firestore服务。

1.Firestore的依赖性

在模块级build.gradle 文件中添加以下依赖关系。

// BoM and Firestore

implementation platform('com.google.firebase:firebase-bom:28.0.1')
implementation 'com.google.firebase:firebase-firestore-ktx'

这声明了Firestore库的依赖性。BoM(Bill of Materials)是一个库,它允许我们使用Firebase库而不指定它们的版本。

也包括这个插件。

plugins{
    id 'com.google.gms.google-services'
}
2.添加classpaths(顶级的build.gradle文件)
dependencies{
    classpath 'com.google.gms:google-services:4.3.8'
}

不要忘了在Manifest file.NET中添加互联网权限。

<uses-permission android:name="android.permission.INTERNET"/>

同步并等待gradle构建完成。

我们已经成功地将Firebase项目连接到我们的Android应用。打开Firebase控制台,你应该看到与此类似的东西。注意该项目在底部有一个小的Android图标,表明它已经连接到了Android平台。

Firebase projects

创建Cloud Firestore数据库

现在设置完成了,我们可以继续创建一个Cloud Firestore数据库,点击左边面板上相应的项目 "Firestore database "Create database ,如下图所示。

Create databse

Firestore数据安全

Firestore使用各种规则来控制数据库访问。以下是两个常用的规则。

1.测试规则

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if
          request.time < timestamp.date(2021, 7, 12);
    }
  }
}

如果规则保持不变,这允许所有应用程序用户在一个月内对数据库进行读、写和任何其他数据操作活动。在这之后,所有用户都被拒绝访问数据库。因此,这个规则不建议用于生产,但它是测试的首选。

2.需要认证

rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth != null;
    }
  }
}

与测试规则不同,这个only ,允许经过认证的用户访问数据库。对于一般级别的生产应用来说,这个规则是应该去做的。

建立应用程序的用户界面

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btnUploadData"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginHorizontal="8dp"
        app:layout_constraintVertical_bias="0.85"
        android:text="@string/upload_data"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btnReadData"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="@string/retrieve_data"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="@+id/btnUploadData"
        app:layout_constraintStart_toStartOf="@+id/btnUploadData"
        app:layout_constraintTop_toBottomOf="@+id/btnUploadData" />
</androidx.constraintlayout.widget.ConstraintLayout>

这将创建两个按钮。它们将分别用于触发uploadread data 任务。在strings.xml 文件中添加缺少的字符串。

<resources>
    <string name="upload_data">Upload data</string>
    <string name="retrieve_data">Retrieve data</string>
</resources>

启用viewBinding

视图绑定允许我们通过它们所属的XML layout 的绑定类访问视图。在模块级gradle 文件中添加下面的代码块,并同步你的项目。

android{
    ...

    buildFeatures{
        viewBinding true
    }
}

膨胀用户界面

const val TAG = "FIRESTORE"

class MainActivity : AppCompatActivity() {
    private var binding: ActivityMainBinding? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding?.root)

        // we'll call functions here
    }

在这里,我们已经利用viewBinding来相应地膨胀UI。我们还声明了一个全局常量变量,它将在我们的日志信息中作为一个标签使用。

数据库操作

使用测试规则。数据库中的操作包括创建、读取、更新和删除,也被称为CRUD操作。

创建数据库实例

创建一个名为FirebaseUtilsKotlin 类,并在其中粘贴以下代码。

class FirebaseUtils {
        val fireStoreDatabase = FirebaseFirestore.getInstance()
}

这作为一个API,允许我们在数据库中add,get,delete, 和update 集合和文档。

1.上传数据

当点击upload 按钮时,将启动一个上传动作。将以下内容粘贴在MainActivity.kt 文件中。

private fun uploadData() {
    binding!!.btnUploadData.setOnClickListener {

        // create a dummy data
        val hashMap = hashMapOf<String, Any>(
            "name" to "John doe",
            "city" to "Nairobi",
            "age" to 24
        )

        // use the add() method to create a document inside users collection
        FirebaseUtils().fireStoreDatabase.collection("users")
            .add(hashMap)
            .addOnSuccessListener {
                Log.d(TAG, "Added document with ID ${it.id}")
            }
            .addOnFailureListener { exception ->
                Log.w(TAG, "Error adding document $exception")
            }
    }

onCreate() 方法中调用这个函数。

override fun onCreate(savedInstanceState: Bundle?) {
    ...
    
    uploadData()
}

如果任务成功,这将添加一个样本数据并记录文件的ID。否则,会抛出一个异常并记录下来。当我们试图在没有互联网连接和/或权限的情况下进行上传,或者数据库规则不允许我们这样做时,就会出现异常。

为了确认数据库已经启动并运行,在Firebase控制台打开它,你应该看到类似这样的东西。

Saved data

根据我们上传的次数,会创建多个数量的文件。这些文件属于users 集合,这就是为什么我们的数据库中只有一个集合。

2.读取数据
private fun readData{
    binding!!.btnReadData.setOnClickListener {
            FirebaseUtils().fireStoreDatabase.collection("users")
                .get()
                .addOnSuccessListener { querySnapshot ->
                    querySnapshot.forEach { document ->
                        Log.d(TAG, "Read document with ID ${document.id}")
                    }
                }
                .addOnFailureListener { exception ->
                    Log.w(TAG, "Error getting documents $exception")
                }
        }
}

这里我们使用get() 方法来检索users 集合中的所有文档。打开Logcat来检查数据是否被成功检索到。

Logs

结论

就这样吧!你现在可以在你的Android应用中实现Firestore云数据库。这可以进一步推进,从用户那里获得输入数据,并使用Kotlin coroutines上传/检索,以获得流畅的性能。