在我的应用中,我只是尝试通过在以下代码中添加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);
}
});
当有互联网连接时,它工作得很好。但是,当我故意关闭互联网连接时,onDataChange
和onCancelled
都没有被调用。这非常令人沮丧,因为databaseError.getCode()
中的两个错误代码与网络连接问题有关。
如果由于没有互联网而无法获取此数据,我想至少让用户知道,而不是让这个监听器挂在屏幕上不断加载。有办法解决这个问题吗?我是否必须使用Firebase's
REST API?至少对于RESTful网络请求,它们会通知您连接是否失败。
答案 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"))
}
}
说实话,我不太喜欢增加两个侦听器的想法,如果其他人有更好且优雅的解决方案,请告诉我,我暂时拥有此代码,直到找到更好的东西为止。