android - 在应用程序被发送到后台之前应用程序无法运行
问题描述
我正在 Kotlin + Firebase 中制作 Instagram 克隆,试图添加“查找要关注的用户”功能。它工作正常,从 Firebase 加载信息,但在我重构代码后,它不会向用户显示,直到我锁定屏幕或折叠/展开应用程序。之后信息就会弹出来。
我只是从 Firebase 查询所有用户并显示除活跃用户之外的所有人。我试图调试这个问题,发现it.children.map { it.asUser()!! }
由于某种原因在活动开始时不会触发。
这是我的代码:
FindUsersActivity
package com.example.imagegram.screens.findusers
import android.os.Bundle
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.imagegram.R
import com.example.imagegram.screens.common.BaseActivity
import com.example.imagegram.models.User
import kotlinx.android.synthetic.main.activity_find_users.*
//@Suppress("DEPRECATION")
class FindUsersActivity : BaseActivity(),
UsersAdapter.Listener {
private lateinit var mUser: User
private lateinit var mUsers: List<User>
private lateinit var mAdapter: UsersAdapter
private lateinit var mViewModel: FindUsersViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_find_users)
mAdapter = UsersAdapter(this)
mViewModel = initViewModel()
find_users_back_image.setOnClickListener { finish() }
find_users_recycler.adapter = mAdapter
find_users_recycler.layoutManager = LinearLayoutManager(this)
mViewModel.userAndFriends.observe(this, Observer {
it?.let { (user, otherUsers) ->
mUser = user
mUsers = otherUsers
mAdapter.update(mUsers, mUser.follows)
}
})
}
override fun follow(uid: String) {
setFollow(uid, true) {
mAdapter.followed(uid)
}
}
override fun unfollow(uid: String) {
setFollow(uid, false) {
mAdapter.unfollowed(uid)
}
}
private fun setFollow(uid: String, follow: Boolean, onSuccess: () -> Unit) {
mViewModel.setFollow(mUser.uid, uid, follow)
.addOnSuccessListener { onSuccess() }
}
companion object {
const val TAG = "FindUsersActivity"
}
}
FindUsersViewModel
package com.example.imagegram.screens.findusers
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import com.example.imagegram.data.FeedPostsRepository
import com.example.imagegram.data.UsersRepository
import com.example.imagegram.data.common.map
import com.example.imagegram.models.User
import com.google.android.gms.tasks.OnFailureListener
import com.google.android.gms.tasks.Task
import com.google.android.gms.tasks.Tasks
class FindUsersViewModel(
private val onFailureListener: OnFailureListener,
private val usersRepo: UsersRepository,
private val FeedPostsRepo: FeedPostsRepository
) : ViewModel() {
// only let Activity work with LiveData
// so that it could not change anything itself but could access it for reading
val userAndFriends: LiveData<Pair<User, List<User>>> =
usersRepo.getUsers().map { allUsers ->
val (userList, otherUsersList) = allUsers.partition {
it.uid == usersRepo.currentUid()
}
userList.first() to otherUsersList
}
fun setFollow(currentUid: String, uid: String, follow: Boolean): Task<Void> {
return if (follow) {
Tasks.whenAll(
usersRepo.addFollow(currentUid, uid),
usersRepo.addFollower(currentUid, uid),
FeedPostsRepo.copyFeedPosts(postsAuthorUid = uid, toUid = currentUid)
)
} else {
Tasks.whenAll(
usersRepo.deleteFollow(currentUid, uid),
usersRepo.deleteFollower(currentUid, uid),
FeedPostsRepo.deleteFeedPosts(postsAuthorUid = uid, toUid = currentUid)
)
}.addOnFailureListener(onFailureListener)
}
}
用户存储库
package com.example.imagegram.data
import android.net.Uri
import androidx.lifecycle.LiveData
import com.example.imagegram.models.User
import com.google.android.gms.tasks.Task
interface UsersRepository {
fun getUsers(): LiveData<List<User>>
fun currentUid(): String?
fun addFollow(fromUid: String, toUid: String): Task<Unit>
fun deleteFollow(fromUid: String, toUid: String): Task<Unit>
fun addFollower(fromUid: String, toUid: String): Task<Unit>
fun deleteFollower(fromUid: String, toUid: String): Task<Unit>
fun getUser(): LiveData<User>
fun uploadUserPhoto(localImage: Uri): Task<Uri>
fun updateUserPhoto(downloadUrl: Uri): Task<Unit>
fun updateEmail(currentEmail: String, newEmail: String, password: String): Task<Unit>
fun updateUserProfile(currentUser: User, newUser: User): Task<Unit>
}
FirebaseUsers 存储库:
package com.example.imagegram.data.firebase
import android.net.Uri
import androidx.lifecycle.LiveData
//import androidx.lifecycle.map
import com.example.imagegram.data.firebase.common.asUser
import com.example.imagegram.utils.toUnit
//import com.example.imagegram.activities.map
import com.example.imagegram.common.task
import com.example.imagegram.data.UsersRepository
import com.example.imagegram.data.common.map
import com.example.imagegram.models.User
import com.example.imagegram.utils.*
import com.google.android.gms.tasks.Task
import com.google.android.gms.tasks.Tasks
import com.google.firebase.auth.EmailAuthProvider
import com.google.firebase.auth.FirebaseAuth
class FirebaseUsersRepository :
UsersRepository {
override fun uploadUserPhoto(localImage: Uri): Task<Uri> =
task { taskSource ->
storage.child("users/${currentUid()!!}/photo").putFile(localImage)
.addOnSuccessListener {
getUrl().addOnCompleteListener {
taskSource.setResult(it.result!!)
}
// Tasks.forResult(getUrl().result!!) //it?.downloadUrl!!)
}
}
override fun getUsers(): LiveData<List<User>> = database.child("users").liveData().map {
it.children.map { it.asUser()!! }
}
override fun addFollow(fromUid: String, toUid: String): Task<Unit> =
getFollowsRef(fromUid, toUid).setValue(true).toUnit()
override fun deleteFollow(fromUid: String, toUid: String): Task<Unit> =
getFollowsRef(fromUid, toUid).removeValue().toUnit()
override fun addFollower(fromUid: String, toUid: String): Task<Unit> =
getFollowersRef(fromUid, toUid).setValue(true).toUnit()
override fun deleteFollower(fromUid: String, toUid: String): Task<Unit> =
getFollowersRef(fromUid, toUid).removeValue().toUnit()
private fun getFollowsRef(fromUid: String, toUid: String) =
database.child("users").child(fromUid).child("follows").child(toUid)
private fun getFollowersRef(fromUid: String, toUid: String) =
database.child("users").child(toUid).child("followers")
.child(fromUid)
override fun currentUid() = FirebaseAuth.getInstance().currentUser?.uid
private fun getUrl() = storage.child("users/${currentUid()!!}/photo").downloadUrl
override fun updateUserPhoto(downloadUrl: Uri): Task<Unit> =
database.child("users/${currentUid()!!}/photo").setValue(downloadUrl.toString()).toUnit()
override fun updateEmail(currentEmail: String, newEmail: String, password: String): Task<Unit> {
val credential = EmailAuthProvider.getCredential(currentEmail, password) // get credential
val currentUser = auth.currentUser
return if (currentUser != null) {
currentUser.reauthenticate(credential).onSuccessTask {//try to re-authentiate
currentUser.updateEmail(newEmail)
}.toUnit()
} else {
Tasks.forException(IllegalStateException("User is not authenticated"))
}
}
override fun updateUserProfile(currentUser: User, newUser: User): Task<Unit> {
val updatesMap = mutableMapOf<String, Any?>()
if (newUser.name != currentUser.name) updatesMap["name"] = newUser.name
if (newUser.username != currentUser.username) updatesMap["username"] = newUser.username
if (newUser.email != currentUser.email) updatesMap["email"] = newUser.email
return database.child("users").child(currentUid()!!).updateChildren(updatesMap).toUnit()
}
override fun getUser(): LiveData<User> =
database.child("users").child(currentUid()!!).liveData().map {
it.asUser()!!
}
}
你知道可能是什么问题吗?任何帮助将不胜感激<3
解决方案
推荐阅读
- java - 如何避免使用双循环来改进这种方法?
- flutter - Flutter 如何在使用自定义滚动视图时(或内部)显示自定义剪辑器
- arm - 尾链 PensSV
- c++ - 如何使用 CMake 确保 Linux 和 Windows 中的相对路径相同
- c++ - 指针和计数问题
- json - 如何在 .NET Core 5.x 中为我的 JSON 字符串创建数据模型
- r - 将绘图添加到文档在函数内部不起作用
- javascript - 如何在以下代码中添加通配符?
- azure - 无法导出我的模型以在 Azure 自定义视觉上进行部署
- react-redux - 如何使用 NextJs 设置 redux 并允许调度操作