Android Firebase - “onDataChange” And “onCancelled” Not Being Called With No Internet Connection

后端 未结 2 614
情书的邮戳
情书的邮戳 2020-12-11 02:01

In my app, I simply try to retrieve a reading passage from my Firebase database by adding a ListenerForSingleValueEvent in the following code:

相关标签:
2条回答
  • 2020-12-11 02:49

    Firebase separates the flow of data events (such as onDataChange()) from other things that might happen. It will only call onCancelled when there is a server-side reason to do so (currently only when the client doesn't have permission to access the data). There is no reason to cancel a listener, just because there is no network connection.

    What you seem to be looking for is a way to detect whether there is a network connection (which is not a Firebase-specific task) or whether the user is connected to the Firebase Database back-end. The latter you can do by attaching a listener to .info/connected, an implicit boolean value that is true when you're connected to the Firebase Database back-end and is false otherwise. See the section in the document on detecting connection state for full details.

    0 讨论(0)
  • 2020-12-11 02:49

    Hope that my solution can help somebody else (I assume that you already did something else)

    Besides to set the keepSynced to true in my database reference:

    databaseRef.keepSynced(true)
    

    And add to my Application class:

    FirebaseDatabase.getInstance().setPersistenceEnabled(true)
    

    I've added two listeners, one for offline mode and other one for online:

    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"))
        }
    }
    

    To be honest, I don't like the idea to attach two listeners very much, if somebody else has a better and elegant solution, please let me know, I have this code temporarily until I find something better.

    0 讨论(0)
提交回复
热议问题