条件';李斯特雷格!=空';始终是';正确';尝试分离/关闭Firestore快照时(Android)

条件';李斯特雷格!=空';始终是';正确';尝试分离/关闭Firestore快照时(Android),android,firebase,kotlin,google-cloud-firestore,Android,Firebase,Kotlin,Google Cloud Firestore,背景:这是我在Android上的第一个项目,我在问一些愚蠢的问题,但我找不到任何方向(当然,我把以前关于Angular/Srping和Android/Kotlin的一些知识弄乱了) 目标:Android应用程序将从某些后端微服务获取Firestore customtoken,然后开始监听文档。到现在为止,一直都还不错。我读过关于如何关闭/分离侦听器的良好实践,我相信通过将Android活动作为第一个参数传递给snapshot,我已经成功地做到了这一点。到目前为止还不错。但在我的情况下,我必须在1

背景:这是我在Android上的第一个项目,我在问一些愚蠢的问题,但我找不到任何方向(当然,我把以前关于Angular/Srping和Android/Kotlin的一些知识弄乱了)

目标:Android应用程序将从某些后端微服务获取Firestore customtoken,然后开始监听文档。到现在为止,一直都还不错。我读过关于如何关闭/分离侦听器的良好实践,我相信通过将Android活动作为第一个参数传递给snapshot,我已经成功地做到了这一点。到目前为止还不错。但在我的情况下,我必须在10分钟后或在收到文档中的特定值后关闭/分离快照侦听。现在我真的被卡住了

我尝试了想象中最简单的第一步,从这个话题中我得到了天真的警告。所以我最直接的问题是:为什么它总是抱怨真实的情况?Android专家的补充意见是,如何在10分钟后关闭/分离快照,以及我是否从文档中收到特定值。请接受以下观点,即这两种情况中的任何一种都需要停止侦听,并仍保持在相同的MainActivity.kt中

以下是在车顶循环阶段尝试检查时出现警告的代码

package com.mycomp.appfirestore

import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.firestore.DocumentSnapshot
import com.google.firebase.firestore.EventListener
import com.google.firebase.firestore.FirebaseFirestore
import com.mycomp.appfirestore.data.service.Endpoint
import com.mycomp.appfirestore.data.service.NetworkUtils
import com.mycomp.appfirestore.model.Transfer
import kotlinx.android.synthetic.main.activity_main.*
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response


class MainActivity : AppCompatActivity() {

    lateinit var auth: FirebaseAuth

    lateinit var listenerReg : FirebaseFirestore

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val btnTransfer = findViewById(R.id.btnTransfer) as Button
        val textViewTransfer = findViewById(R.id.textViewTransfer) as TextView
        btnTransfer.setOnClickListener {
            getToken()
        }
    }

    fun getToken() {
        val retrofitClient = NetworkUtils
            .getRetrofitInstance("http://192.168.15.13:8080/")

        val endpoint = retrofitClient.create(Endpoint::class.java)

...
        callback.enqueue(object : Callback<Transfer> {
            override fun onFailure(call: Call<Transfer>, t: Throwable) {
                Toast.makeText(baseContext, t.message, Toast.LENGTH_SHORT).show()
            }

            override fun onResponse(call: Call<Transfer>, response: Response<Transfer>) {
                listenStatus()
            }
        })

    }

    fun listenStatus() {
        val TAG = "ListenStatus"
        auth = FirebaseAuth.getInstance()

        // to make simple for this question let's say the backend returned a valid customtoken used here
        auth.signInWithCustomToken("eyJ **** gXsQ")
            .addOnCompleteListener(this) { task ->
                if (task.isSuccessful) {
                    Log.d(TAG, "*** signInWithCustomToken:success")
                    startSnapshot()
                } else {
                    // If sign in fails, display a message to the user.
                    Log.w(TAG, "signInWithCustomToken:failure", task.exception)
                    Toast.makeText(
                        baseContext, "Authentication failed.",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            }
    }


    fun startSnapshot() {
        val TAG = "StartSnapshot"

        //Try to pass this(activity context) as first parameter.It will automatically handle acivity life cycle.
        // Example if you are calling this listener in onCreate() and passing this as a first parameter then
        // it will remove this listener in onDestroy() method of activity.
        listenerReg = FirebaseFirestore.getInstance()

        listenerReg.collection("transfer")
            .document("sDme6IRIi4ezfeyfrU7y")
            .addSnapshotListener(
                this,
                EventListener<DocumentSnapshot?> { snapshot, e ->
                    if (e != null) {
                        Log.w(TAG, "Listen failed.", e)
                        return@EventListener
                    }
                    if (snapshot != null && snapshot.exists()) {
                        textViewTransfer.text = snapshot.data!!["status"].toString()
                        //Log.d(TAG, snapshot.data!!["status"].toString())
                    } else {
                        Log.d(TAG, "Current data: null")
                    }
                })

    }
//here I get the warnning mentioned in my question topic
fun stopSnapshot() {
    if (listenerReg != null) {
        listenerReg.remove()
    }
}
}
package com.mycop.appfirestore
导入android.os.Bundle
导入android.util.Log
导入android.widget.Button
导入android.widget.TextView
导入android.widget.Toast
导入androidx.appcompat.app.appcompat活动
导入com.google.firebase.auth.FirebaseAuth
导入com.google.firebase.firestore.DocumentSnapshot
导入com.google.firebase.firestore.EventListener
导入com.google.firebase.firestore.FirebaseFirestore
导入com.mycop.appfirestore.data.service.Endpoint
导入com.mycop.appfirestore.data.service.NetworkUtils
导入com.mycop.appfirestore.model.Transfer
导入kotlinx.android.synthetic.main.activity\u main*
2.致电
导入2.回调
2.回应
类MainActivity:AppCompatActivity(){
lateinit var auth:FirebaseAuth
lateinit var listenerReg:FirebaseFirestore
重写创建时的乐趣(savedInstanceState:Bundle?){
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val btnTransfer=findViewById(R.id.btnTransfer)as按钮
val textViewTransfer=findViewById(R.id.textViewTransfer)作为TextView
btnTransfer.setOnClickListener{
getToken()
}
}
乐趣{
val-client=NetworkUtils
.GetInstance(“http://192.168.15.13:8080/")
val endpoint=client.create(endpoint::class.java)
...
排队(对象:callback{
覆盖失效时的乐趣(调用:调用,t:可丢弃){
Toast.makeText(baseContext、t.message、Toast.LENGTH\u SHORT.show())
}
覆盖fun onResponse(调用:调用,响应:响应){
李斯特状态()
}
})
}
有趣的李斯特状态(){
val TAG=“ListenStatus”
auth=FirebaseAuth.getInstance()
//为了简化这个问题,假设后端返回了此处使用的有效customtoken
使用CustomToken(“eyJ****gXsQ”)进行授权签名
.addOnCompleteListener(此){task->
如果(任务成功){
Log.d(标记“***使用CustomToken登录:成功”)
startSnapshot()
}否则{
//如果登录失败,则向用户显示消息。
Log.w(标记“signInWithCustomToken:failure”,task.exception)
Toast.makeText(
baseContext,“身份验证失败。”,
吐司长度
).show()
}
}
}
有趣的开始{
val TAG=“StartSnapshot”
//尝试将此(活动上下文)作为第一个参数传递。它将自动处理活动生命周期。
//例如,如果在onCreate()中调用此侦听器并将其作为第一个参数传递,则
//它将在活动的onDestroy()方法中删除此侦听器。
listenerReg=FirebaseFirestore.getInstance()
listenerReg.集合(“转移”)
.文件(“sDme6IRIi4ezfeyfrU7y”)
.addSnapshotListener(
这
EventListener{快照,e->
如果(e!=null){
Log.w(标记“侦听失败”,e)
return@EventListener
}
if(snapshot!=null&&snapshot.exists()){
textViewTransfer.text=snapshot.data!![“状态”].toString()
//Log.d(标记,快照.data!![“状态”].toString())
}否则{
Log.d(标记“当前数据:空”)
}
})
}
//在这里,我得到了我的问题主题中提到的警告
有趣的快照(){
如果(listenerReg!=null){
listenerReg.remove()
}
}
}
我知道,由于我添加了activity作为snapshot的第一个参数,因此该activity很快就会离开,它将自动分离侦听。但我还有两个条件要停止倾听:

1-10分钟后

2-如果我得到一个特定的返回值

所以,作为想象的解决方案,我会或多或少地尝试

EventListener{snapshot,e->
如果(e!=null){
Log.w(标记“侦听失败”,e)
return@EventListener
}
if(snapshot!=null&&snapshot.exists()){
textViewTransfer.text=snapshot.data!![“状态”].toString()
****想象的解决方案****
if(snapshot.data!![“status”].toStr
        EventListener<DocumentSnapshot?> { snapshot, e ->
            if (e != null) {
                Log.w(TAG, "Listen failed.", e)
                return@EventListener
            }
            if (snapshot != null && snapshot.exists()) {
                textViewTransfer.text = snapshot.data!!["status"].toString()
                **** imagined solution ****
                if (snapshot.data!!["status"].toString() == "FINISH"){
                   stopSnapshot()
                }
                //Log.d(TAG, snapshot.data!!["status"].toString())
            } else {
                Log.d(TAG, "Current data: null")
            }
        })
        ...
        **** imagined solution ***
        listenerReg.timeout(10000, stopSnapshot())