TBR: TODOs: Factoring out persistence
TODO(rosswang): Rename things now that hierarchy is clear.
Change-Id: I68f6268e9d2aa82fd8df2986d378fa7dca4def56
diff --git a/projects/todos/app/src/main/java/io/v/todos/KeyedData.java b/projects/todos/app/src/main/java/io/v/todos/KeyedData.java
index 20da7ad..7abae0d 100644
--- a/projects/todos/app/src/main/java/io/v/todos/KeyedData.java
+++ b/projects/todos/app/src/main/java/io/v/todos/KeyedData.java
@@ -10,6 +10,7 @@
*
* @author alexfandrianto
*/
-public abstract class KeyedData<T> implements Comparable<T> {
- public abstract String getKey();
+public interface KeyedData<T> extends Comparable<T> {
+ String getKey();
+ void setKey(String key);
}
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 0157f18..56f2f0c 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
@@ -11,7 +11,6 @@
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
-import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -19,12 +18,8 @@
import android.widget.EditText;
import android.widget.Toolbar;
-import com.firebase.client.ChildEventListener;
-import com.firebase.client.DataSnapshot;
-import com.firebase.client.Firebase;
-import com.firebase.client.FirebaseError;
-
-import io.v.todos.persistence.Persistence;
+import io.v.todos.persistence.ListEventListener;
+import io.v.todos.persistence.MainPersistence;
import io.v.todos.persistence.PersistenceFactory;
/**
@@ -38,27 +33,20 @@
* @author alexfandrianto
*/
public class MainActivity extends Activity {
- static final String FIREBASE_EXAMPLE_URL = "https://vivid-heat-7354.firebaseio.com/";
- private Persistence mPersistence;
- private Firebase myFirebaseRef; // TODO(rosswang): migrate
+ private MainPersistence mPersistence;
// Snackoos are the code name for the list of todos.
// These todos are backed up at the SNACKOOS child of the Firebase URL.
// We use the snackoosList to track a custom sorted list of the stored values.
static final String INTENT_SNACKOO_KEY = "snackoo key";
- static final String INTENT_SNACKOO_VALUE = "snackoo value";
- static final String SNACKOOS = "snackoos (TodoList)";
private DataList<TodoList> snackoosList = new DataList<TodoList>();
// This adapter handle mirrors the firebase list values and generates the corresponding todo
// item View children for a list view.
private TodoListRecyclerAdapter adapter;
- private ChildEventListener snackoosEventListener;
-
@Override
protected void onDestroy() {
- myFirebaseRef.removeEventListener(snackoosEventListener);
mPersistence.close();
super.onDestroy();
}
@@ -72,13 +60,12 @@
getActionBar().setTitle(R.string.app_name);
// Set up the todo list adapter
- final Activity self = this;
adapter = new TodoListRecyclerAdapter(snackoosList, new View.OnClickListener() {
@Override
public void onClick(View view) {
String fbKey = (String)view.getTag();
- Intent intent = new Intent(self, TodoListActivity.class);
+ Intent intent = new Intent(MainActivity.this, TodoListActivity.class);
intent.putExtra(INTENT_SNACKOO_KEY, fbKey);
startActivity(intent);
}
@@ -92,41 +79,19 @@
@Override
public void onSwiped(final RecyclerView.ViewHolder viewHolder, final int direction) {
if (direction == ItemTouchHelper.RIGHT) {
- Log.d(SNACKOOS, "Gonna mark all tasks as done");
-
- // TODO(alexfandrianto): This doesn't do anything yet. Should mark all child Tasks as done.
+ // TODO(alexfandrianto): This doesn't do anything yet. Should mark all child
+ // Tasks as done.
adapter.notifyDataSetChanged();
} else if (direction == ItemTouchHelper.LEFT) {
- Log.d(SNACKOOS, "Gonna delete this todo list");
- deleteTodoItem((String)viewHolder.itemView.getTag());
+ mPersistence.deleteTodoList((String)viewHolder.itemView.getTag());
}
}
}).attachToRecyclerView(recyclerView);
- // Prepare our Firebase Reference and the primary listener (SNACKOOS).
- mPersistence = PersistenceFactory.getPersistence(this);
- myFirebaseRef = new Firebase(FIREBASE_EXAMPLE_URL);
- setUpSnackoos();
- }
-
- // Set the visibility based on what the adapter thinks is the visible item count.
- private void setEmptyVisiblity() {
- View v = findViewById(R.id.empty);
- v.setVisibility(adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
- }
-
- // Any time a child of SNACKOOS is added/changed/removed, we mirror the changes locally.
- private void setUpSnackoos() {
- snackoosEventListener = firebaseListReference().addChildEventListener(new ChildEventListener() {
+ mPersistence = PersistenceFactory.getMainPersistence(this, new ListEventListener<TodoList>() {
@Override
- public void onChildAdded(DataSnapshot dataSnapshot, String prevKey) {
- String fbKey = dataSnapshot.getKey();
- TodoList todoList = dataSnapshot.getValue(TodoList.class);
- todoList.setKey(fbKey);
-
- // Insert in order.
- snackoosList.insertInOrder(todoList);
-
+ public void onInsert(TodoList item) {
+ snackoosList.insertInOrder(item);
adapter.notifyDataSetChanged();
// TODO(alexfandrianto): In order to capture the computed values for this TodoList,
@@ -136,47 +101,27 @@
}
@Override
- public void onChildChanged(DataSnapshot dataSnapshot, String prevKey) {
- String fbKey = dataSnapshot.getKey();
- TodoList todoList = dataSnapshot.getValue(TodoList.class);
- todoList.setKey(fbKey);
-
- snackoosList.updateInOrder(todoList);
+ public void onUpdate(TodoList item) {
+ snackoosList.updateInOrder(item);
adapter.notifyDataSetChanged();
}
@Override
- public void onChildRemoved(DataSnapshot dataSnapshot) {
- String fbKey = dataSnapshot.getKey();
- snackoosList.removeByKey(fbKey);
+ public void onDelete(String key) {
+ snackoosList.removeByKey(key);
adapter.notifyDataSetChanged();
// TODO(alexfandrianto): Stop watching the Task data for this TodoList.
setEmptyVisiblity();
}
-
- @Override
- public void onChildMoved(DataSnapshot dataSnapshot, String prevKey) {
-
- }
-
- @Override
- public void onCancelled(FirebaseError firebaseError) {
-
- }
});
}
- private Firebase firebaseListReference() {
- return myFirebaseRef.child(SNACKOOS);
- }
- public void addTodoItem(String todo) {
- firebaseListReference().push().setValue(new TodoList(todo));
- }
-
- public void deleteTodoItem(String fbKey) {
- firebaseListReference().child(fbKey).removeValue();
+ // Set the visibility based on what the adapter thinks is the visible item count.
+ private void setEmptyVisiblity() {
+ View v = findViewById(R.id.empty);
+ v.setVisibility(adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
}
public void addCallback(View view) {
@@ -187,14 +132,15 @@
.setView(todoItem)
.setPositiveButton("Add", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
- addTodoItem(todoItem.getText().toString());
+ mPersistence.addTodoList(new TodoList(todoItem.getText().toString()));
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
}
}).show();
- dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
+ dialog.getWindow().setSoftInputMode(
+ WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
}
// The following methods are boilerplate for handling the Menu in the top right corner.
diff --git a/projects/todos/app/src/main/java/io/v/todos/Task.java b/projects/todos/app/src/main/java/io/v/todos/Task.java
index 98b6146..79698d9 100644
--- a/projects/todos/app/src/main/java/io/v/todos/Task.java
+++ b/projects/todos/app/src/main/java/io/v/todos/Task.java
@@ -12,7 +12,7 @@
* @author alexfandrianto
*/
@JsonIgnoreProperties({ "key" })
-public class Task extends KeyedData<Task> {
+public class Task implements KeyedData<Task> {
private String text;
private long addedAt;
private boolean done;
diff --git a/projects/todos/app/src/main/java/io/v/todos/TodoList.java b/projects/todos/app/src/main/java/io/v/todos/TodoList.java
index 0361473..31f27a1 100644
--- a/projects/todos/app/src/main/java/io/v/todos/TodoList.java
+++ b/projects/todos/app/src/main/java/io/v/todos/TodoList.java
@@ -12,7 +12,7 @@
* @author alexfandrianto
*/
@JsonIgnoreProperties({ "numCompleted", "numTasks", "done", "key" })
-public class TodoList extends KeyedData<TodoList> {
+public class TodoList implements KeyedData<TodoList> {
private String name;
private long updatedAt;
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 00535a8..54403de 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
@@ -11,7 +11,6 @@
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
-import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -19,14 +18,9 @@
import android.widget.EditText;
import android.widget.Toolbar;
-import com.firebase.client.ChildEventListener;
-import com.firebase.client.DataSnapshot;
-import com.firebase.client.Firebase;
-import com.firebase.client.FirebaseError;
-import com.firebase.client.ValueEventListener;
-
-import io.v.todos.persistence.Persistence;
import io.v.todos.persistence.PersistenceFactory;
+import io.v.todos.persistence.TodoListListener;
+import io.v.todos.persistence.TodoListPersistence;
/**
* TodoListActivity for Vanadium TODOs
@@ -41,11 +35,8 @@
* @author alexfandrianto
*/
public class TodoListActivity extends Activity {
- private Persistence mPersistence;
- private Firebase myFirebaseRef;
+ private TodoListPersistence mPersistence;
- private final static String SNACKOO_LISTS = "snackoo lists (Task)";
- private String snackooKey;
private TodoList snackoo;
private DataList<Task> snackoosList = new DataList<Task>();
private boolean showDone = false; // TODO(alexfandrianto): Load from shared preferences...
@@ -53,13 +44,9 @@
// This adapter handle mirrors the firebase list values and generates the corresponding todo
// item View children for a list view.
private TaskRecyclerAdapter adapter;
- private ValueEventListener snackooEventListener;
- private ChildEventListener snackoosEventListener;
@Override
protected void onDestroy() {
- myFirebaseRef.removeEventListener(snackooEventListener);
- myFirebaseRef.removeEventListener(snackoosEventListener);
mPersistence.close();
super.onDestroy();
}
@@ -69,13 +56,12 @@
setContentView(R.layout.activity_main);
Intent intent = getIntent();
- snackooKey = intent.getStringExtra(MainActivity.INTENT_SNACKOO_KEY);
+ String snackooKey = intent.getStringExtra(MainActivity.INTENT_SNACKOO_KEY);
Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
setActionBar(toolbar);
// Set up the todo list adapter
- final Activity self = this;
adapter = new TaskRecyclerAdapter(snackoosList, new View.OnClickListener() {
@Override
public void onClick(View view) {
@@ -92,46 +78,44 @@
@Override
public void onSwiped(final RecyclerView.ViewHolder viewHolder, final int direction) {
if (direction == ItemTouchHelper.RIGHT) {
- Log.d(SNACKOO_LISTS, "Gonna mark all tasks as done");
markAsDone((String)viewHolder.itemView.getTag());
} else if (direction == ItemTouchHelper.LEFT) {
- Log.d(SNACKOO_LISTS, "Gonna delete this todo list");
deleteTodoItem((String)viewHolder.itemView.getTag());
}
}
}).attachToRecyclerView(recyclerView);
- // Prepare our Firebase Reference and the primary listener (SNACKOOS).
- mPersistence = PersistenceFactory.getPersistence(this);
- myFirebaseRef = new Firebase(MainActivity.FIREBASE_EXAMPLE_URL);
- setUpSnackoo();
- setUpSnackoos();
- }
-
- private Firebase firebaseListReference() {
- return myFirebaseRef.child(MainActivity.SNACKOOS).child(snackooKey);
- }
-
- private Firebase firebaseTasksReference() {
- return myFirebaseRef.child(SNACKOO_LISTS).child(snackooKey);
- }
-
- private void setUpSnackoo() {
- snackooEventListener = firebaseListReference().addValueEventListener(new ValueEventListener() {
+ mPersistence = PersistenceFactory.getTodoListPersistence(this, snackooKey,
+ new TodoListListener() {
@Override
- public void onDataChange(DataSnapshot dataSnapshot) {
- snackoo = dataSnapshot.getValue(TodoList.class);
- if (snackoo == null) {
- // The list has been deleted. Get the heck out of here!
- finish();
- return;
- }
+ public void onChange(TodoList value) {
+ snackoo = value;
getActionBar().setTitle(snackoo.getName());
}
@Override
- public void onCancelled(FirebaseError firebaseError) {
+ public void onDelete() {
+ finish();
+ }
+ @Override
+ public void onInsert(Task item) {
+ snackoosList.insertInOrder(item);
+ adapter.notifyDataSetChanged();
+ setEmptyVisiblity();
+ }
+
+ @Override
+ public void onUpdate(Task item) {
+ snackoosList.updateInOrder(item);
+ adapter.notifyDataSetChanged();
+ }
+
+ @Override
+ public void onDelete(String key) {
+ snackoosList.removeByKey(key);
+ adapter.notifyDataSetChanged();
+ setEmptyVisiblity();
}
});
}
@@ -142,71 +126,27 @@
v.setVisibility(adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
}
- // Any time a child of SNACKOOS is added/changed/removed, we mirror the changes locally.
- private void setUpSnackoos() {
- snackoosEventListener = firebaseTasksReference().addChildEventListener(new ChildEventListener() {
- @Override
- public void onChildAdded(DataSnapshot dataSnapshot, String prevKey) {
- String fbKey = dataSnapshot.getKey();
- Task task = dataSnapshot.getValue(Task.class);
- task.setKey(fbKey);
- snackoosList.insertInOrder(task);
- adapter.notifyDataSetChanged();
-
- setEmptyVisiblity();
- }
-
- @Override
- public void onChildChanged(DataSnapshot dataSnapshot, String prevKey) {
- String fbKey = dataSnapshot.getKey();
- Task task = dataSnapshot.getValue(Task.class);
- task.setKey(fbKey);
- snackoosList.updateInOrder(task);
- adapter.notifyDataSetChanged();
- }
-
- @Override
- public void onChildRemoved(DataSnapshot dataSnapshot) {
- String fbKey = dataSnapshot.getKey();
- snackoosList.removeByKey(fbKey);
- adapter.notifyDataSetChanged();
-
- setEmptyVisiblity();
- }
-
- @Override
- public void onChildMoved(DataSnapshot dataSnapshot, String prevKey) {
-
- }
-
- @Override
- public void onCancelled(FirebaseError firebaseError) {
-
- }
- });
- }
-
public void addTodoItem(String todo) {
// TODO(alexfandrianto): Turns out these are all batch changes that change the parents updatedAt
- firebaseTasksReference().push().setValue(new Task(todo));
+ mPersistence.addTask(new Task(todo));
}
public void updateTodoItem(String fbKey, String todo) {
// TODO(alexfandrianto): Turns out these are all batch changes that change the parents updatedAt
Task task = snackoosList.findByKey(fbKey).copy();
task.setText(todo);
- firebaseTasksReference().child(fbKey).setValue(task);
+ mPersistence.updateTask(task);
}
public void markAsDone(String fbKey) {
// TODO(alexfandrianto): Turns out these are all batch changes that change the parents updatedAt
Task task = snackoosList.findByKey(fbKey).copy();
task.setDone(!task.getDone());
- firebaseTasksReference().child(fbKey).setValue(task);
+ mPersistence.updateTask(task);
}
public void deleteTodoItem(String fbKey) {
// TODO(alexfandrianto): Turns out these are all batch changes that change the parents updatedAt
- firebaseTasksReference().child(fbKey).removeValue();
+ mPersistence.deleteTask(fbKey);
}
public void addCallback(View view) {
@@ -224,7 +164,8 @@
public void onClick(DialogInterface dialog, int whichButton) {
}
}).show();
- dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
+ dialog.getWindow().setSoftInputMode(
+ WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
}
private void initiateTaskEdit(final String fbKey) {
@@ -248,7 +189,8 @@
public void onClick(DialogInterface dialog, int whichButton) {
}
}).show();
- dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
+ dialog.getWindow().setSoftInputMode(
+ WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
}
private void initiateTodoListEdit() {
@@ -272,16 +214,17 @@
public void onClick(DialogInterface dialog, int whichButton) {
}
}).show();
- dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
+ dialog.getWindow().setSoftInputMode(
+ WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
}
public void updateTodoList(String todo) {
- firebaseListReference().setValue(new TodoList(todo));
+ mPersistence.updateTodoList(new TodoList(todo));
}
public void deleteTodoList() {
- firebaseListReference().removeValue();
+ mPersistence.deleteTodoList();
}
diff --git a/projects/todos/app/src/main/java/io/v/todos/persistence/FirebaseChildEventListenerAdapter.java b/projects/todos/app/src/main/java/io/v/todos/persistence/FirebaseChildEventListenerAdapter.java
new file mode 100644
index 0000000..c38d01e
--- /dev/null
+++ b/projects/todos/app/src/main/java/io/v/todos/persistence/FirebaseChildEventListenerAdapter.java
@@ -0,0 +1,48 @@
+// 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 com.firebase.client.ChildEventListener;
+import com.firebase.client.DataSnapshot;
+import com.firebase.client.FirebaseError;
+
+import io.v.todos.KeyedData;
+
+public class FirebaseChildEventListenerAdapter<T extends KeyedData> implements ChildEventListener {
+ private final Class<T> mType;
+ private final ListEventListener<T> mDelegate;
+
+ public FirebaseChildEventListenerAdapter(Class<T> type, ListEventListener<T> delegate) {
+ mType = type;
+ mDelegate = delegate;
+ }
+
+ @Override
+ public void onChildAdded(DataSnapshot dataSnapshot, String prevKey) {
+ T value = dataSnapshot.getValue(mType);
+ value.setKey(dataSnapshot.getKey());
+ mDelegate.onInsert(value);
+ }
+
+ @Override
+ public void onChildChanged(DataSnapshot dataSnapshot, String prevKey) {
+ T value = dataSnapshot.getValue(mType);
+ value.setKey(dataSnapshot.getKey());
+ mDelegate.onUpdate(value);
+ }
+
+ @Override
+ public void onChildRemoved(DataSnapshot dataSnapshot) {
+ mDelegate.onDelete(dataSnapshot.getKey());
+ }
+
+ @Override
+ public void onChildMoved(DataSnapshot dataSnapshot, String prevKey) {
+ }
+
+ @Override
+ public void onCancelled(FirebaseError firebaseError) {
+ }
+}
diff --git a/projects/todos/app/src/main/java/io/v/todos/persistence/FirebaseMain.java b/projects/todos/app/src/main/java/io/v/todos/persistence/FirebaseMain.java
new file mode 100644
index 0000000..711e8c4
--- /dev/null
+++ b/projects/todos/app/src/main/java/io/v/todos/persistence/FirebaseMain.java
@@ -0,0 +1,43 @@
+// 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;
+
+import com.firebase.client.ChildEventListener;
+import com.firebase.client.Firebase;
+
+import io.v.todos.TodoList;
+
+public class FirebaseMain extends FirebasePersistence implements MainPersistence {
+ public static final String TODO_LISTS = "snackoos (TodoList)";
+
+ private final Firebase mTodoLists;
+ private final ChildEventListener mTodoListsListener;
+
+ public FirebaseMain(Context context, final ListEventListener<TodoList> listener) {
+ super(context);
+
+ mTodoLists = getFirebase().child(TODO_LISTS);
+
+ mTodoListsListener = mTodoLists.addChildEventListener(
+ new FirebaseChildEventListenerAdapter<>(TodoList.class, listener));
+ }
+
+ @Override
+ public void addTodoList(TodoList todoList) {
+ mTodoLists.push().setValue(todoList);
+ }
+
+ @Override
+ public void deleteTodoList(String key) {
+ mTodoLists.child(key).removeValue();
+ }
+
+ @Override
+ public void close() {
+ getFirebase().removeEventListener(mTodoListsListener);
+ }
+}
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 cd208c0..fbc8180 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
@@ -14,13 +14,21 @@
*
* @author alexfandrianto
*/
-public class FirebasePersistence implements Persistence {
+public abstract class FirebasePersistence implements Persistence {
+ private static final String FIREBASE_EXAMPLE_URL = "https://vivid-heat-7354.firebaseio.com/";
+
static {
// Set up Firebase to persist data locally even when offline. This must be set before
// Firebase is used.
Firebase.getDefaultConfig().setPersistenceEnabled(true);
}
+ private final Firebase mFirebase;
+
+ protected Firebase getFirebase() {
+ return mFirebase;
+ }
+
/**
* Instantiates a persistence object that can be used to manipulate data.
*
@@ -30,10 +38,7 @@
// 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);
- }
- @Override
- public void close() {
- // TODO(rosswang): Remove listeners.
+ mFirebase = new Firebase(FIREBASE_EXAMPLE_URL);
}
}
diff --git a/projects/todos/app/src/main/java/io/v/todos/persistence/FirebaseTodoList.java b/projects/todos/app/src/main/java/io/v/todos/persistence/FirebaseTodoList.java
new file mode 100644
index 0000000..000cc47
--- /dev/null
+++ b/projects/todos/app/src/main/java/io/v/todos/persistence/FirebaseTodoList.java
@@ -0,0 +1,82 @@
+// 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;
+
+import com.firebase.client.ChildEventListener;
+import com.firebase.client.DataSnapshot;
+import com.firebase.client.Firebase;
+import com.firebase.client.FirebaseError;
+import com.firebase.client.ValueEventListener;
+
+import io.v.todos.Task;
+import io.v.todos.TodoList;
+
+public class FirebaseTodoList extends FirebasePersistence implements TodoListPersistence {
+ public static final String TASKS = "snackoo lists (Task)";
+
+ private final Firebase mTodoList, mTasks;
+ private final ValueEventListener mTodoListListener;
+ private final ChildEventListener mTasksListener;
+
+ public FirebaseTodoList(Context context, String todoListKey, final TodoListListener listener) {
+ super(context);
+
+ mTodoList = getFirebase().child(FirebaseMain.TODO_LISTS).child(todoListKey);
+ mTasks = getFirebase().child(TASKS).child(todoListKey);
+
+ mTodoListListener = mTodoList.addValueEventListener(new ValueEventListener() {
+ @Override
+ public void onDataChange(DataSnapshot dataSnapshot) {
+ TodoList todoList = dataSnapshot.getValue(TodoList.class);
+ if (todoList == null) {
+ listener.onDelete();
+ } else {
+ listener.onChange(todoList);
+ }
+ }
+
+ @Override
+ public void onCancelled(FirebaseError firebaseError) {
+
+ }
+ });
+
+ mTasksListener = mTasks.addChildEventListener(
+ new FirebaseChildEventListenerAdapter<>(Task.class, listener));
+ }
+
+ @Override
+ public void updateTodoList(TodoList todoList) {
+ mTodoList.setValue(todoList);
+ }
+
+ @Override
+ public void deleteTodoList() {
+ mTodoList.removeValue();
+ }
+
+ @Override
+ public void addTask(Task task) {
+ mTasks.push().setValue(task);
+ }
+
+ @Override
+ public void updateTask(Task task) {
+ mTasks.child(task.getKey()).setValue(task);
+ }
+
+ @Override
+ public void deleteTask(String key) {
+ mTasks.child(key).removeValue();
+ }
+
+ @Override
+ public void close() {
+ getFirebase().removeEventListener(mTodoListListener);
+ getFirebase().removeEventListener(mTasksListener);
+ }
+}
diff --git a/projects/todos/app/src/main/java/io/v/todos/persistence/ListEventListener.java b/projects/todos/app/src/main/java/io/v/todos/persistence/ListEventListener.java
new file mode 100644
index 0000000..0e0641e
--- /dev/null
+++ b/projects/todos/app/src/main/java/io/v/todos/persistence/ListEventListener.java
@@ -0,0 +1,11 @@
+// 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 ListEventListener<T> {
+ void onInsert(T item);
+ void onUpdate(T item);
+ void onDelete(String key);
+}
diff --git a/projects/todos/app/src/main/java/io/v/todos/persistence/MainPersistence.java b/projects/todos/app/src/main/java/io/v/todos/persistence/MainPersistence.java
new file mode 100644
index 0000000..1fbbef5
--- /dev/null
+++ b/projects/todos/app/src/main/java/io/v/todos/persistence/MainPersistence.java
@@ -0,0 +1,12 @@
+// 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 io.v.todos.TodoList;
+
+public interface MainPersistence extends Persistence {
+ void addTodoList(TodoList todoList);
+ void deleteTodoList(String key);
+}
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
index 104c180..9a34a11 100644
--- 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
@@ -6,16 +6,30 @@
import android.content.Context;
+import io.v.todos.TodoList;
+
public final class PersistenceFactory {
private PersistenceFactory(){}
/**
- * Instantiates a persistence object that can be used to manipulate data.
+ * Instantiates a persistence object that can be used to manipulate todo lists.
*
* @param context an Android context, usually from an Android activity or application
*/
- public static Persistence getPersistence(Context context) {
+ public static MainPersistence getMainPersistence(Context context,
+ ListEventListener<TodoList> listener) {
// TODO(rosswang): Choose this by build variant.
- return new FirebasePersistence(context);
+ return new FirebaseMain(context, listener);
+ }
+
+ /**
+ * Instantiates a persistence object that can be used to manipulate a todo list.
+ *
+ * @param context an Android context, usually from an Android activity or application
+ */
+ public static TodoListPersistence getTodoListPersistence(Context context, String key,
+ TodoListListener listener) {
+ // TODO(rosswang): Choose this by build variant.
+ return new FirebaseTodoList(context, key, listener);
}
}
diff --git a/projects/todos/app/src/main/java/io/v/todos/persistence/TodoListListener.java b/projects/todos/app/src/main/java/io/v/todos/persistence/TodoListListener.java
new file mode 100644
index 0000000..9632de9
--- /dev/null
+++ b/projects/todos/app/src/main/java/io/v/todos/persistence/TodoListListener.java
@@ -0,0 +1,13 @@
+// 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 io.v.todos.Task;
+import io.v.todos.TodoList;
+
+public interface TodoListListener extends ListEventListener<Task> {
+ void onChange(TodoList value);
+ void onDelete();
+}
diff --git a/projects/todos/app/src/main/java/io/v/todos/persistence/TodoListPersistence.java b/projects/todos/app/src/main/java/io/v/todos/persistence/TodoListPersistence.java
new file mode 100644
index 0000000..8ec2117
--- /dev/null
+++ b/projects/todos/app/src/main/java/io/v/todos/persistence/TodoListPersistence.java
@@ -0,0 +1,16 @@
+// 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 io.v.todos.Task;
+import io.v.todos.TodoList;
+
+public interface TodoListPersistence extends Persistence {
+ void updateTodoList(TodoList todoList);
+ void deleteTodoList();
+ void addTask(Task task);
+ void updateTask(Task task);
+ void deleteTask(String key);
+}