本文概述
- 将数据写入Firestore
- 从Firestore读取数据
- 将Cloud Firestore与Kotlin Extension一起使用
- 将DocumentSnapshot字段转换为普通的旧Java对象
- QuerySnapshot转换为普通的旧Java对象
在本部分中, 我们将学习如何在Firebase Firestore中完成读取和写入操作。以前, 我们创建了一个android应用程序, 并为其添加了Firebase。我们已经实现了所有必需的库和插件。我们之前已经创建了一个Firestore数据库。
将数据写入Firestore
为了写入数据, 我们必须使用getInstance()检索数据库的实例, 并引用要写入的位置。我们将从活动中访问Cloud Firestore实例。
val db=FirebaseFirestore.getInstance()
众所周知, 数据存储在文档中, 而这些文档存储在集合中。因此, 我们将隐式创建集合和文档。当我们第一次向文档中添加数据时, 将自动创建集合。让我们看一个将地图添加到集合中的示例。
//Creating a new user with a first and last name
val user=hashMapOff(
"first" to"Shubham", "last" to "Rastogi"
"born" to 1815
)
//Adding a new document with generated ID
db.collection("users").add(user).addOnSuccessListener { documentReference ->
Log.w(TAG, "DocumentSnapshot added with ID:${documentReference.id}")
}
.addOnFailureListener{e ->
Log.w(TAG, "Error adding document", e)
}
有几种将数据写入Cloud Firestore的方法, 如下所示:
- 第一种方式, 我们在集合中设置文档的数据, 显式指定文档标识符。
- 通过将新文档添加到集合中, 我们可以将数据写入数据库。 Cloud Firestore自动生成文档标识符。
- 我们可以通过创建带有自动生成的标识符的空文档来将数据写入数据库。数据将在以后分配给它。
设定文件
我们使用set()方法创建或覆盖单个文档。当使用set()方法创建文档时, 必须为要创建的文档指定ID。
db.collection("cities").document("new-city-id").set(data)
val city = hashMapOf(
"name" to "Noida"
"state" to "UP"
"country" to "India"
)
db.collection("cities").document("LA").set(city)
当我们使用set()创建文档时, 让Cloud Firestore为我们自动生成ID(add())更加方便。
// Adding a new document with a generated id
val data=hashMapOf(
"name" to "UP"
"country" to "India"
)
db.collection("cities").add(data)
.addOnSuccessListener{
documentReference -> Log.d(TAG, "DocumentSnapshot written with ID:${documentReference.id}")
}
.addOnFailureListener{
e->Log.w(TAG, "Error adding document", e)
}
创建具有自动生成的ID的文档引用, 然后再使用引用稍后(doc())也可能很有用。
val data=HashMap<String, Any>()
val newCityRef=db.collection("cities").document()
//Later...
newCityRef.set(data)
资料类型
我们可以在文档中编写各种数据类型和对象。
val docData=hashMapOf(
"stringExample" to "srcmini", "booleanExample" to true, "numberExample" to 3.14159265, "dateExample" to Timestamp(Date()), "listExample" to arrayListOf(1, 2, 3), "nullExample" to null
)
val nestedData=hashMapOf(
"a" to 5, "b" to true
)
docData["objectExample"]=nestedData
db.collection("data").document("one")
.set(docData)
.addOnSuccessListener{Log.d(Tag, "DocumentSnapshot successfullyt written")}
.addOnFailureListener{e->Log.w(TAG, "Error writing document", e)}
自定义对象
我们可以使用自定义类编写自己的java对象。这些自定义类在内部将对象转换为受支持的数据类型。每个列类都必须具有不带任何参数的公共构造函数, 并且该类的每个属性都必须具有公共获取器。
data class City(
val name:String?=null, val state:String?=null, val country:String?=null, val isCapital:Boolean?=null, val population:Long?=null, val regions:List<String>?=null
)
val city=City("Noida", "UP", "India", false, 5000000L, listOf("west_coast", "social"))
db.collection("cities").document("LA").set(city)
从Firestore读取数据
db.collection("users")
.get().addOnSuccessListener{result->
for(document in result){
Log.d(TAG, "${document.id}=>${document.data}")
}
}
.addOnFailureListener{exception->
Log.w(TAG, "Error getting documents.", exception)
}
有两种检索数据的方法, 这些方法存储在Cloud Firestore中。
- 调用方法以获取数据。
- 设置侦听器以接收数据会更改事件。我们发送数据的初始快照, 然后在文档更改时发送另一个快照。
这两种方法都可用于文档, 文档集合或查询结果。让我们以一个示例为例, 在该示例中, 我们用一些有关城市的数据填充数据库。
val data1=hashMapOf(
"name" to "noida"
"state" to "UP"
"country" to "USA"
"capital" to false, "population" to 860000, "regions" to listOf("hinduism", "Muslims")
)
cities.document("SF").set(data1)
使用自定义对象
val docRef=db.collection("cities").document("Bj")
docRef.get().addonSuccessListener{
documentSnapshot ->
val city=documentSnapshot.toObject(City::class.java)
}
从集合中获取多个文档
我们还可以通过查询集合中的文档来检索多个文档。我们可以使用where()来查询满足一定条件的所有文档, 然后使用get()来检索结果。
db.collection("cities").whereEqualTo("capital", true).get()
.addOnSuccessListener{ documents ->
for(document in documents){
Log.d(TAG, "${document.id}=>${document.data}")
}
}
.addOnFailureListener{exception ->
Log.w(TAG, "Error getting documents:", exception)
}
从集合中获取多个文档
db.collection("cities").get()
.addOnSuccessListener{ documents ->
for(document in documents){
Log.d(TAG, "${document.id}=>${document.data}")
}
}
.addOnFailureListener{exception ->
Log.w(TAG, "Error getting documents:", exception)
}
将Cloud Firestore与Kotlin Extension一起使用
如果我们想将Cloud Firestore Android SDK与Kotlin Extensions一起使用, 我们必须在应用程序的buid.gradle文件中添加以下库:
我们必须确保有最新版本的maven.google.com。该库可传递地包含firebase-Firestore库。
Implementation 'com.google.firebase: firebase-firestore-ktx: 18.2.0'
科特林
val Firestore=FirebaseFirestore.getInstance()
val anotherFirestore=FirebaseFirestore.getInstance(FirebaseApp.getInstance("myApp"))
Kotlin + KTX
val Firestore=Firebase.firestore
val anotherFirestore=Firebase.firestore(Firebase.app("myApp"))
将DocumentSnapshot字段转换为普通的旧Java对象
1)科特林
val snapshot: DocumentSnapshot=...
val myObject=snapshot.get("fieldPath", MyClass::class.java)
要么
val snapshot: DocumentSnapshot=...
val myObject=snapshot.toObject(MyClass::class.java)
2)Kotlin + KTX
val snapshot: DocumentSnapshot=...
val myObject=snapshot.get<MyClass>("fieldPath")
要么
val snapshot: DocumentSnapshot=...
val myObject=snapshot.toObject<MyClass>()
QuerySnapshot转换为普通的旧Java对象
1)科特林
val snapshot: QuerySnapshot=...
val myObject=snapshot.toObject(MyClass::class.java)
2)Kotlin + KTX
val snapshot: QuerySnapshot=...
val myObject=snapshot.toObject<MyClass>()
例:
我们正在实现一个android应用程序。这是一个用户日志记录和注册应用程序, 具有三个xml文件和四个Kotlin文件。 activity_main.xml用于注册页面。 activity_signing.xml用于登录, activity_welcome.xml用于从数据库检索数据。同样, 有四个Kotlin文件, 即MainActivity, Signing, welcome和User。
当用户注册自己时, 会将他们添加到firebase控制台用户部分, 并将与他们相对应的数据存储在数据库中。签名功能与我们在身份验证部分中所做的相同。用户成功注册或注册后, 将切换到欢迎页面, 在该页面上可以找到他的数据。
activity_main.xml, activity_signing和activity_welcome
MainActivity.kt
package com.example.firestoreexample
import android.content.Intent
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.view.View
import android.widget.Toast
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.firestore.FirebaseFirestore
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
private var mAuth: FirebaseAuth?=null
private var mFirebaseDatabaseInstances:FirebaseFirestore?=null
private var userId:String?=null
private var emailAddress:String?=null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//Get Firebase Instances
mAuth=FirebaseAuth.getInstance()
mFirebaseDatabaseInstances= FirebaseFirestore.getInstance()
//if already logged in go to sign in screen
if(mAuth!!.currentUser!=null){
startActivity(Intent(this, welcome::class.java))
finish()
}
}
fun onLoginClicked(view: View) {
startActivity(Intent(this, signing::class.java))
finish()
}
fun onRegisterClicked(view: View) {
if(TextUtils.isEmpty(username.text.toString())){
Toast.makeText(applicationContext, "Enter Username!", Toast.LENGTH_LONG).show()
}
if(TextUtils.isEmpty(email.text.toString())){
Toast.makeText(applicationContext, "Enter email address!", Toast.LENGTH_LONG).show()
}
if(TextUtils.isEmpty(password.text.toString())){
Toast.makeText(applicationContext, "Enter password!", Toast.LENGTH_LONG).show()
}
if(password.text.toString().length<6){
Toast.makeText(applicationContext, "Password is too short", Toast.LENGTH_LONG).show()
}
progressBar!!.visibility=View.VISIBLE
//create user
mAuth!!.createUserWithEmailAndPassword(email.text.toString(), password.text.toString())
.addOnCompleteListener(this){task ->
Toast.makeText(this, "createUserWithEmail:onComplete"+task.isSuccessful, Toast.LENGTH_SHORT).show()
progressBar.visibility=View.GONE
if(task.isSuccessful){
val user=FirebaseAuth.getInstance().currentUser
//add username, email to database
userId=user!!.uid
emailAddress=user.email
val myUser=user(username.text.toString(), emailAddress!!)
mFirebaseDatabaseInstances?.collection("users")?.document(userId!!)?.set(myUser)
startActivity(Intent(this, welcome::class.java))
finish()
}else{
Toast.makeText(this, "Authentication Failed"+task.exception, Toast.LENGTH_SHORT).show()
Log.e("MyTag", task.exception.toString())
}
}
}
}
welcome.kt
package com.example.firestoreexample
import android.content.Intent
import android.nfc.Tag
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.constraintlayout.solver.widgets.Snapshot
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.database.*
import com.google.firebase.firestore.FirebaseFirestore
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.activity_main.email
import kotlinx.android.synthetic.main.activity_main.username
import kotlinx.android.synthetic.main.activity_welcome.*
class welcome : AppCompatActivity() {
private var mFirebaseDatabaseInstance:FirebaseFirestore?=null
private var userId:String?=null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_welcome)
mFirebaseDatabaseInstance= FirebaseFirestore.getInstance()
val user=FirebaseAuth.getInstance().currentUser
//add it only if it is not saved to database
if (user != null) {
userId=user.uid
Log.e(TAG, "User data is null")
}
getDataOneTime()
}
private fun getDataOneTime(){
//getting the data onetime
val docRef=mFirebaseDatabaseInstance?.collection("users")?.document(userId!!)
docRef?.get()?.addOnSuccessListener { documentSnapshot ->
val user=documentSnapshot.toObject(user::class.java)
Log.e(TAG, "user data is changed"+user?.name+", "+user?.email)
//Display newly updated name and email
txt_user.setText(user?.name+", "+user?.email)
//Clear edit text
email.setText(user?.email)
username.setText(user?.name)
}
}
fun onLogout(view: View) {
FirebaseAuth.getInstance().signOut()
startActivity(Intent(this, MainActivity::class.java))
}
companion object{
private val TAG=welcome::class.java.simpleName
}
}
输出:
评论前必须登录!
注册