Recent Posts
Firebase Connection Management
This is the second article in our series about Firebase. Read part 1 here.
When using an app connected to only one Firebase database, Android usually provides all of the connection management we need without us having to worry about it. However, if we’re connecting to multiple instances in one app, we may have to do some management on our own, since we can only have one active connection per database instance at any time. Firebase connection instances are singletons, so whenever we switch connections we need to know the status of our connection in case we need to switch back.
Here’s what we get automatically, courtesy of the Firebase documentation:
“On Android, Firebase automatically manages connection state to reduce bandwidth and battery usage. When a client has no active listeners, no pending write or onDisconnect operations, and is not explicitly disconnected by the goOffline() method, Firebase closes the connection after 60 seconds of inactivity.”
As mentioned above, you can use the goOffline() method to disconnect manually. However, you do need to be careful of your active listeners, because these will keep connections open. You can get rid of listeners you no longer need with removeEventListener(myLoggingListener) This has to be done before you call goOffline() because active listeners will prevent you from closing a connection manually.
If you need a listener that goes away after getting a single event, there’s a specific listener class available for that which you can get by using the method addListenerForSingleValueEvent. Once this listener is fired, it is removed automatically. All other listeners, including CompletionListener, will persist for multiple events. Here’s an example use of addListenerForSingleValueEvent:
scansRef.push().setValue(event); scansRef.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { Log.d(TAG, "Firebase successfully synched to remote server()"); Toast.makeText(getApplicationContext(), "Check " + (radioButton_checkIn.isChecked() ? "In" : "Out") + " completed.", Toast.LENGTH_LONG).show(); scansRef.goOffline(); finish(); } @Override public void onCancelled(DatabaseError databaseError) { Log.w(TAG, “Firebase error” + databaseError.getMessage(); } });
In this example, I’m expecting to push things to my firebase database (scansRef ) infrequently, so after my listener has fired, I disconnect from my firebase instance.
One way to help simplify connection management is to put connections in an Application object, and get an instance of the application to make sure you’re only attempting to a database once.
Alternatively, we can use a try/catch block as follows, keeping initialization within the activity that uses the database object:
private FirebaseApp getFbApp(final String appName) { try { sApp = FirebaseApp.getInstance(appName); } catch (IllegalStateException se) { // We get illegal state exception if given appName hasn't been initialized yet. FirebaseOptions options = new FirebaseOptions.Builder() .setApplicationId("second_db_application_id") .setApiKey("second_db_api_key") .setDatabaseUrl("https://second.db.url.firebaseio.com/") .build(); FirebaseApp.initializeApp(getApplicationContext(), options, secondAppName); } try { sApp = FirebaseApp.getInstance(secondAppName); } catch (IllegalStateException se) { se.printStackTrace(); } } return sApp; }