android - FIRESTORE 持久数据

标签 android firebase kotlin google-cloud-firestore persistent

谈论 firestore 持久数据,假设用户第一次启动应用程序时没有任何连接。我向 Firestore 数据库添加一些数据(例如 userID..),我可以使用 get() 方法将其取回。现在用户关闭应用程序。

  1. 下次他打开应用程序(仍然没有连接)时,他是否能够检索之前存储的数据,就像以共享首选项的方式存储一样? 我无法清楚地弄清楚如何找到正确的方法来设置具有持久数据的初始化阶段。

  2. 我有几个 fragment 。每次启动其中一个时,我都会使用“onResume”方法从数据(之前存储在sharedpref中)填充我的组件。当我设置 Firestore getData 时,检索需要时间。因此,如果用户从当前 fragment 更改为另一个 fragment ,当连接打开时,在数据库结果完成时,我会收到有关组件为空或无法访问的错误。

    实现此类“onResume”数据重新填充的最佳方式是什么?

更新:

这里是一些代码:MainAvtivity.kt

FirebaseFirestore.getInstance().firestoreSettings.isPersistenceEnabled
        sightingsDatabase = FirebaseFirestore.getInstance()
        docname=FireStoreSetup().setupFB(sightingsDatabase!!,this)

一个 kotlin 对象类来填充我的文档:

data class Sighting(var userID: String,
                    var sig_wit_situation_type: Int,
                    var sig_env_background_type: Int,
                    var sig_ground_type: Int,
                    var sig_YYYY: String,
                    var sig_MM: String,
                    var sig_DD: String,
                    var sig_time_start: String,
                    var sig_date_time: String,
                    var sig_duration_hms: String,
                    var sig_duration_milli: Int,
                    var sig_weather_full: Int,
                    var sig_temp: Int)

FireStoreSetup 类中:第一次初始化发生时 ->

val sighting = Sighting(deviceId!!,
                        0,
                        0,
                        0,
                        strDate.substring(0, 4),
                        strDate.substring(5, 7),
                        strDate.substring(8, 10),
                        strDate.substring(11),
                        strDate,
                        "00:00:00",
                        0,
                        0,
                        0)

                db.collection("users").document(docname!!)
                        .set(sighting)
                        .addOnSuccessListener {
                            Log.d(_tag, "DocumentSnapshot successfully written!")
                            setShared(context,"doc_name",docname!!)}
                        .addOnFailureListener { e -> Log.w(_tag, "Error writing document", e) }

然后向服务器写入数据很有趣

fun addValue(key:String,value:Any?){
        val docData = HashMap<String,Any?>()
        docData.put(key, value)
        FirebaseFirestore.getInstance().collection("users").document(docname!!)
                .set(docData, SetOptions.merge())
    }

 fun readValue(){
        val docRef = FirebaseFirestore.getInstance().collection("users").document(docname!!)
        docRef.addSnapshotListener(object:EventListener<DocumentSnapshot> {
            override fun onEvent(snapshot:DocumentSnapshot?, e:FirebaseFirestoreException?) {
                if (e != null)
                {
                    Log.w("firestore", "Listen failed.", e)
                }
                if (snapshot != null && snapshot.exists())
                {
                    Log.d("firestore", "Current data: " + snapshot.getData())
                    FragmentHome.vars=snapshot.getData()
                }
                else
                {
                    Log.d("firestore", "Current data: null")
                }
            }
        })
    }

FragmentHome中:

companion object {
        val itemsMenu = ArrayList<MenuData>()
        var vars: MutableMap<String,Any>? =null

        fun newInstance(value: Int): FragmentHome {
            val args = Bundle()
            args.putInt("menu", value)
            val fragment = FragmentHome()
            fragment.arguments = args
            return fragment
        }

    }

override fun onResume() {
        super.onResume()
        FireStoreSetup().readValue()
        when (_menu){
            0-> switchRecycler(1,0)
            1-> switchRecycler(0,0)
        }
    }

然后从fragmentHome,将其替换为具有firestore值的新 fragment :

val situ= vars!!["sig_wit_situation_type"].toString().toInt()
            val env= vars!!["sig_env_background_type"].toString().toInt()
            val grd= vars!!["sig_ground_type"].toString().toInt()
reFrag(FragmentSitu.newInstance(situ,env,grd), 1)

在新的 FragmentSitu fragment 中,我们有:

companion object {
        fun newInstance(situ: Int,env: Int,grd: Int): FragmentSitu {
            val args = Bundle()
            args.putInt("sig_wit_situation_type", situ)
            args.putInt("sig_env_background_type", env)
            args.putInt("sig_ground_type", grd)

            val fragment = FragmentSitu()
            fragment.arguments = args
            return fragment
        }
    }

感谢 Franck 和 docRef.addSnapshotListener,无论在线还是离线,它都可以毫无延迟地运行。

** 必须有更好的方法来捕获 onEvent(snapshot:DocumentSnapshot?) 中的 snapshot.getData() 结果,正如我希望设置的那样我的 fragment 参数 FragmentSitu.newInstance(situ,env,grd) 直接来自 snapshot.getData()["situ"], snapshot.getData()["env"] ...

最佳答案

此处为 firebaser

Firestore 将您在设备上写入的数据保存到本地数据库。因此,下次启动应用程序时,即使设备从未连接到 Firebase 服务器,它也确实能够读取相同的数据。

当您的应用首次尝试从 Firestore 读取数据时,它会尝试与其服务器建立连接。如果您是using get() calls to read the data Firestore 将等待该连接建立或失败,然后再返回数据。这意味着这个初始调用可能需要相当长的时间。我们知道这可能会导致您的应用的用户出现不良行为,因此我们正在寻找改进这种行为的方法。

同时,考虑using realtime listeners读取相同的数据。这些监听器在这种情况下的行为有所不同,并且将/可能提供两次结果:

  1. 第一个快照会立即给出,并且来自本地缓存。
  2. 在客户端收到云数据库的响应后,稍后会提供第二个快照。

关于android - FIRESTORE 持久数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47434582/

相关文章:

java - 如何避免 Java/Kotlin/IntelliJ IDEA 中的 StackOverFlow 错误?

android - 动态应用样式

java - zipalign 未随 Java SDK/JRE 一起安装

android - 在android中实现加载屏幕的最佳方式

java - 如何初始化 firebase 托管在 google app-engine 上的 spring-boot 应用程序

javascript - 如何将 limit 和 startAt 应用于 firestore 文档的子项目

java - 无法通过 ToolProvider 找到 jpackage

android - Bitmap.compress 为绘制的图像返回 false

swift - 仅在获取用户位置后获取 Firebase/Geofire 数据

android - 为 Kotlin 多平台项目运行单元测试时出错