Android Firebase - 无法通过互联网连接调用“onDataChange”和“onCancelled”

时间:2016-08-18 14:53:32

标签: android firebase firebase-realtime-database

在我的应用中,我只是尝试通过在以下代码中添加Firebase来检索ListenerForSingleValueEvent数据库中的阅读段落:

myRef.child("passages").child(passageNum).addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                System.out.println("ON DATA CHANGE");
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {
                System.out.println("DATABASE ERROR");
                FirebaseErrorHandler.handleDatabaseError(databaseError.getCode(), ReadingActivity.this);
            }

        });

当有互联网连接时,它工作得很好。但是,当我故意关闭互联网连接时,onDataChangeonCancelled都没有被调用。这非常令人沮丧,因为databaseError.getCode()中的两个错误代码与网络连接问题有关。

如果由于没有互联网而无法获取此数据,我想至少让用户知道,而不是让这个监听器挂在屏幕上不断加载。有办法解决这个问题吗?我是否必须使用Firebase's REST API?至少对于RESTful网络请求,它们会通知您连接是否失败。

2 个答案:

答案 0 :(得分:7)

Firebase将数据事件流(例如onDataChange())与可能发生的其他事件分开。只有在出于服务器端原因时才会调用onCancelled(目前仅在客户端没有访问数据的权限时)。没有理由取消监听器,因为没有网络连接。

您似乎正在寻找的方法是检测是否存在网络连接(这不是特定于Firebase的任务)或用户是否连接到Firebase数据库后端。后者可以通过将监听器附加到.info/connected来实现,当您连接到Firebase数据库后端时,隐式布尔值为true,否则为false。有关详细信息,请参阅document on detecting connection state中的部分。

答案 1 :(得分:1)

希望我的解决方案可以帮助其他人(我假设您已经做过其他事情)

除了在数据库参考中将keepSynced设置为true之外:

databaseRef.keepSynced(true)

并添加到我的Application类:

FirebaseDatabase.getInstance().setPersistenceEnabled(true)

我添加了两个侦听器,一个用于离线模式,另一个用于在线:

override fun create(data: BaseObject): Observable<String> {
    return Observable.create { observer ->
        val objectId = databaseRef.push().key
        objectId?.let { it ->
            data.id = it

            val valueEvent = object : ValueEventListener {
                override fun onCancelled(e: DatabaseError) {
                    observer.onError(e.toException())
                }

                override fun onDataChange(dataSnapshot: DataSnapshot) {
                    observer.onComplete()
                }
            }
            // This listener will be triggered if we try to push data without an internet connection
            databaseRef.addListenerForSingleValueEvent(valueEvent)

            // The following listeners will be triggered if we try to push data with an internet connection
            databaseRef.child(it)
                    .setValue(data)
                    .addOnCompleteListener {
                        observer.onComplete()
                        // If we are at this point we don't need the previous listener
                        databaseRef.removeEventListener(valueEvent)
                    }
                    .addOnFailureListener { e ->
                        if (!observer.isDisposed) {
                            observer.onError(e)
                        }
                        databaseRef.removeEventListener(valueEvent)
                    }
        } ?: observer.onError(FirebaseApiNotAvailableException("Cannot create new $reference Id"))
    }
}

说实话,我不太喜欢增加两个侦听器的想法,如果其他人有更好且优雅的解决方案,请告诉我,我暂时拥有此代码,直到找到更好的东西为止。