TBR: Prepping Firebase for persistence abstraction

Switching from singleton to instantiatable with static configuration. It
turns setAndroidContext is idempotent; setPersistenceEnabled was causing
the exception on rotation, and that should be cheap enough to do in a
static initializer.

Change-Id: I604718c7c54809594157527af9092fa8dd7ab23d
diff --git a/projects/todos/app/src/main/java/io/v/todos/MainActivity.java b/projects/todos/app/src/main/java/io/v/todos/MainActivity.java
index e2229b8..0157f18 100644
--- a/projects/todos/app/src/main/java/io/v/todos/MainActivity.java
+++ b/projects/todos/app/src/main/java/io/v/todos/MainActivity.java
@@ -24,7 +24,8 @@
 import com.firebase.client.Firebase;
 import com.firebase.client.FirebaseError;
 
-import io.v.todos.persistence.FirebasePersistence;
+import io.v.todos.persistence.Persistence;
+import io.v.todos.persistence.PersistenceFactory;
 
 /**
  * MainActivity for Vanadium TODOs
@@ -38,7 +39,8 @@
  */
 public class MainActivity extends Activity {
     static final String FIREBASE_EXAMPLE_URL = "https://vivid-heat-7354.firebaseio.com/";
-    private Firebase myFirebaseRef;
+    private Persistence mPersistence;
+    private Firebase myFirebaseRef; // TODO(rosswang): migrate
 
     // Snackoos are the code name for the list of todos.
     // These todos are backed up at the SNACKOOS child of the Firebase URL.
@@ -57,6 +59,7 @@
     @Override
     protected void onDestroy() {
         myFirebaseRef.removeEventListener(snackoosEventListener);
+        mPersistence.close();
         super.onDestroy();
     }
 
@@ -101,7 +104,7 @@
         }).attachToRecyclerView(recyclerView);
 
         // Prepare our Firebase Reference and the primary listener (SNACKOOS).
-        FirebasePersistence.getDatabase(this);
+        mPersistence = PersistenceFactory.getPersistence(this);
         myFirebaseRef = new Firebase(FIREBASE_EXAMPLE_URL);
         setUpSnackoos();
     }
diff --git a/projects/todos/app/src/main/java/io/v/todos/TodoListActivity.java b/projects/todos/app/src/main/java/io/v/todos/TodoListActivity.java
index d049da2..00535a8 100644
--- a/projects/todos/app/src/main/java/io/v/todos/TodoListActivity.java
+++ b/projects/todos/app/src/main/java/io/v/todos/TodoListActivity.java
@@ -25,7 +25,8 @@
 import com.firebase.client.FirebaseError;
 import com.firebase.client.ValueEventListener;
 
-import io.v.todos.persistence.FirebasePersistence;
+import io.v.todos.persistence.Persistence;
+import io.v.todos.persistence.PersistenceFactory;
 
 /**
  * TodoListActivity for Vanadium TODOs
@@ -40,6 +41,7 @@
  * @author alexfandrianto
  */
 public class TodoListActivity extends Activity {
+    private Persistence mPersistence;
     private Firebase myFirebaseRef;
 
     private final static String SNACKOO_LISTS = "snackoo lists (Task)";
@@ -58,6 +60,7 @@
     protected void onDestroy() {
         myFirebaseRef.removeEventListener(snackooEventListener);
         myFirebaseRef.removeEventListener(snackoosEventListener);
+        mPersistence.close();
         super.onDestroy();
     }
 
@@ -99,7 +102,7 @@
         }).attachToRecyclerView(recyclerView);
 
         // Prepare our Firebase Reference and the primary listener (SNACKOOS).
-        FirebasePersistence.getDatabase(this);
+        mPersistence = PersistenceFactory.getPersistence(this);
         myFirebaseRef = new Firebase(MainActivity.FIREBASE_EXAMPLE_URL);
         setUpSnackoo();
         setUpSnackoos();
diff --git a/projects/todos/app/src/main/java/io/v/todos/persistence/FirebasePersistence.java b/projects/todos/app/src/main/java/io/v/todos/persistence/FirebasePersistence.java
index 0e11636..cd208c0 100644
--- a/projects/todos/app/src/main/java/io/v/todos/persistence/FirebasePersistence.java
+++ b/projects/todos/app/src/main/java/io/v/todos/persistence/FirebasePersistence.java
@@ -9,30 +9,31 @@
 import com.firebase.client.Firebase;
 
 /**
- * TODO(alexfandrianto): We may want to shove a lot more into this singleton and have it subclass
+ * TODO(alexfandrianto): We may want to shove a lot more into this class and have it subclass
  * a common interface with Syncbase. I want this to also manage data watches and changes.
  *
  * @author alexfandrianto
  */
-public class FirebasePersistence {
-    private FirebasePersistence() {} // Marked private to prevent accidental instantiation.
-
-    private static FirebasePersistence singleton;
+public class FirebasePersistence implements Persistence {
+    static {
+        // Set up Firebase to persist data locally even when offline. This must be set before
+        // Firebase is used.
+        Firebase.getDefaultConfig().setPersistenceEnabled(true);
+    }
 
     /**
-     * Obtain a database singleton that can be used to manipulate data.
+     * Instantiates a persistence object that can be used to manipulate data.
      *
-     * @param context An Android context, usually from an Android activity or application.
-     * @return
+     * @param context an Android context, usually from an Android activity or application
      */
-    public synchronized static FirebasePersistence getDatabase(Context context) {
-        if (singleton == null) {
-            singleton = new FirebasePersistence();
+    public FirebasePersistence(Context context) {
+        // This no-ops if the context has already been set, and calls getApplicationContext so we
+        // don't have to worry about leaking activity contexts.
+        Firebase.setAndroidContext(context);
+    }
 
-            // Set up Firebase with the context and have it persist data locally even when offline.
-            Firebase.setAndroidContext(context);
-            Firebase.getDefaultConfig().setPersistenceEnabled(true);
-        }
-        return singleton;
+    @Override
+    public void close() {
+        // TODO(rosswang): Remove listeners.
     }
 }
diff --git a/projects/todos/app/src/main/java/io/v/todos/persistence/Persistence.java b/projects/todos/app/src/main/java/io/v/todos/persistence/Persistence.java
new file mode 100644
index 0000000..7b74e2d
--- /dev/null
+++ b/projects/todos/app/src/main/java/io/v/todos/persistence/Persistence.java
@@ -0,0 +1,9 @@
+// Copyright 2016 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package io.v.todos.persistence;
+
+public interface Persistence extends AutoCloseable {
+    void close();
+}
diff --git a/projects/todos/app/src/main/java/io/v/todos/persistence/PersistenceFactory.java b/projects/todos/app/src/main/java/io/v/todos/persistence/PersistenceFactory.java
new file mode 100644
index 0000000..104c180
--- /dev/null
+++ b/projects/todos/app/src/main/java/io/v/todos/persistence/PersistenceFactory.java
@@ -0,0 +1,21 @@
+// Copyright 2016 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package io.v.todos.persistence;
+
+import android.content.Context;
+
+public final class PersistenceFactory {
+    private PersistenceFactory(){}
+
+    /**
+     * Instantiates a persistence object that can be used to manipulate data.
+     *
+     * @param context an Android context, usually from an Android activity or application
+     */
+    public static Persistence getPersistence(Context context) {
+        // TODO(rosswang): Choose this by build variant.
+        return new FirebasePersistence(context);
+    }
+}
diff --git a/projects/todos/app/src/main/java/io/v/todos/persistence/SyncbasePersistence.java b/projects/todos/app/src/main/java/io/v/todos/persistence/SyncbasePersistence.java
index a6ea458..80c78b8 100644
--- a/projects/todos/app/src/main/java/io/v/todos/persistence/SyncbasePersistence.java
+++ b/projects/todos/app/src/main/java/io/v/todos/persistence/SyncbasePersistence.java
@@ -4,5 +4,8 @@
 
 package io.v.todos.persistence;
 
-public class SyncbasePersistence {
+public class SyncbasePersistence implements Persistence {
+    @Override
+    public void close() {
+    }
 }