mr.*_*oot 5 android kotlin firebase google-cloud-firestore kotlin-coroutines
Kotlin我用和创建了一个应用程序Firebase Firestore。现在我需要实现协程,因为主线程上有很多工作。但我也是一个初学者,所以这对我来说是新的东西。我看过一些关于此的教程,但没有找到完整的教程Firestore协程的完整教程。所以我需要一些帮助来在我的应用程序中实现协程,在这样的部分(我自己尝试过,但没有得到它)。
从 Firestore 检索帖子。
private fun retrievePosts() {
FirebaseFirestore.getInstance().collection("Posts")
.orderBy("timeStamp", Query.Direction.DESCENDING)
.get()
.addOnSuccessListener { queryDocumentSnapshots ->
postList?.clear()
for (documentSnapshot in queryDocumentSnapshots) {
val post = documentSnapshot.toObject(Post::class.java)
postList?.add(post)
}
postAdapter?.notifyDataSetChanged()
postAdapter?.setOnPostClickListener(this)
if (isRefreshed) {
swipe_refresh_home?.setRefreshing(false)
isRefreshed = false
}
swipe_refresh_home?.visibility = VISIBLE
progress_bar_home?.visibility = GONE
}.addOnFailureListener { e ->
Log.d(TAG, "UserAdapter-retrieveUsers: ", e)
swipe_refresh_home?.visibility = VISIBLE
progress_bar_home?.visibility = GONE
}
}
Run Code Online (Sandbox Code Playgroud)
将用户数据放入适配器
private fun userInfo( fullName: TextView, profileImage: CircleImageView,
about: TextView, uid: String,
userLocation: TextView, itemRoot: LinearLayout ) {
val userRef = FirebaseFirestore.getInstance().collection("Users").document(uid)
userRef.get()
.addOnSuccessListener {
if (it != null && it.exists()) {
val user = it.toObject(User::class.java)
Glide.with(mContext).load(user?.getImage()).placeholder(R.drawable.default_pro_pic).into(profileImage)
fullName.text = user?.getFullName().toString()
about.text = user?.getAbout()
if (user?.getLocation() != ""){
userLocation.visibility = VISIBLE
userLocation.text = user?.getLocation()
}
if (profileImage.drawable == null){
itemRoot.visibility = GONE
}
else{
itemRoot.visibility = VISIBLE
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
以及适配器中的“保存帖子”按钮。
private fun savedPost(postId: String, saveButton: ImageView?) {
FirebaseFirestore.getInstance().collection("Users").document(currentUserID)
.collection("Saved Posts").document(postId)
.get()
.addOnSuccessListener {
if (it.exists()) {
saveButton?.setImageResource(drawable.ic_bookmark)
} else {
saveButton?.setImageResource(drawable.bookmark_post_ic)
}
}
}
Run Code Online (Sandbox Code Playgroud)
正如我看到您的代码,您正在使用以下查询:
val queryPostsByTimestamp = FirebaseFirestore.getInstance().collection("Posts")
.orderBy("timeStamp", Query.Direction.DESCENDING)
Run Code Online (Sandbox Code Playgroud)
最有可能从“Posts”集合中获取 Post 对象的列表。
为了使用Kotlin Coroutines,不要忘记在 Gradle (app) 文件中添加以下依赖项:
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.3.9"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.3.1"
Run Code Online (Sandbox Code Playgroud)
我将为您提供使用 MVVM 架构模式的解决方案。因此,我们将使用存储库类和 ViewModel 类。对于对 Firestore 的异步调用,我们将使用Flow。
对于从数据库调用中获得的响应,我们需要一个如下所示的密封类:
sealed class Response<out T> {
class Loading<out T>: Response<T>()
data class Success<out T>(
val data: T
): Response<T>()
data class Failure<out T>(
val errorMessage: String
): Response<T>()
}
Run Code Online (Sandbox Code Playgroud)
假设您有一个“Post”类,让我们在存储库类中创建以下函数:
fun getPostsFromFirestore() = flow {
emit(Loading())
emit(Success(queryPostsByTimestamp.get().await().documents.mapNotNull { doc ->
doc.toObject(Post::class.java)
}))
}. catch { error ->
error.message?.let { errorMessage ->
emit(Failure(errorMessage))
}
}
Run Code Online (Sandbox Code Playgroud)
所以我们将根据状态发出一个对象。第一次调用该函数时,我们使用 发出加载状态emit(Loading(),当我们获取数据时,我们发出List<Post>,如果出现错误,我们使用 发出错误消息 Failure(errorMessage)。
现在我们需要从 ViewModel 类调用此函数:
fun getPosts() = liveData(Dispatchers.IO) {
repository.getPostsFromFirestore().collect { response ->
emit(response)
}
}
Run Code Online (Sandbox Code Playgroud)
通过上述函数,我们收集从 getPostsFromFirestore() 函数调用获得的数据,并将结果作为 LiveData 对象进一步发出,以便可以在活动/片段中观察到它,如下所示:
private fun getPosts() {
viewModel.getPosts().observe(this, { response ->
when(response) {
is Loading -> //Load a ProgessBar
is Success -> {
val postList = response.data
//Do what you need to do with your list
//Hide the ProgessBar
}
is Failure -> {
print(response.errorMessage)
//Hide the ProgessBar
}
}
})
}
Run Code Online (Sandbox Code Playgroud)
差不多就这些了!
我不了解 Firebase,所以我可能会错过一些东西,但一般来说,您不需要库中的特殊支持即可将其与协程一起使用。如果您启动一个后台协程,然后在其中执行上述代码,那么 Firebase 可能会在您的协程中运行而不会出现任何问题。
唯一有问题的部分可能是听众。有些库在用于执行它们的线程中调用回调,但有些库将回调分派到特定线程。对于 Firebase,默认情况下它似乎在主线程中运行侦听器。如果这不是您想要的,您也可以传递一个执行器来在协程中运行回调,例如:
.addOnSuccessListener(Dispatchers.Default.asExecutor()) { ... }
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3996 次 |
| 最近记录: |