Skip to content

Instantly share code, notes, and snippets.

@wonsuc
Created May 11, 2019 14:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wonsuc/90803dcf9e8179bcddac8bda62217e99 to your computer and use it in GitHub Desktop.
Save wonsuc/90803dcf9e8179bcddac8bda62217e99 to your computer and use it in GitHub Desktop.
package app.pwdr.firebase.manager;
import android.annotation.SuppressLint;
import android.util.Log;
import app.pwdr.firebase.model.FIRObject;
import com.google.android.gms.tasks.Task;
import com.google.android.gms.tasks.TaskCompletionSource;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseException;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.MutableData;
import com.google.firebase.database.Query;
import com.google.firebase.database.Transaction;
import com.google.firebase.database.ValueEventListener;
import java.util.Map;
public class DatabaseManager {
public static String TAG = "DatabaseManager";
private DatabaseManager() {
}
public static FirebaseDatabase getDatabase() {
return FirebaseDatabase.getInstance();
}
public static DatabaseReference getRef() {
return getDatabase().getReference();
}
public static DatabaseReference getRef(String path) {
return getDatabase().getReference(path);
}
public static Task<Void> setValue(DatabaseReference ref, Object o) {
Log.i(TAG, "setValue:ref:" + (ref != null ? ref.toString() : "null"));
return ref.setValue(o);
}
public static Task<Void> updateChildren(Map<String, Object> map) {
Log.i(TAG, "updateChildren:map:" + map.toString());
return getRef().updateChildren(map);
}
public static Task<Void> updateChildren(DatabaseReference ref, Map<String, Object> map) {
Log.i(TAG, "updateChildren:map:" + map.toString());
return ref.updateChildren(map);
}
public static Task<DataSnapshot> getValue(DatabaseReference ref) {
final TaskCompletionSource<DataSnapshot> tcs = new TaskCompletionSource<>();
Log.d(TAG, "getValue:ref:" + ref.toString());
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d(TAG, "getValue:onDataChange");
tcs.setResult(dataSnapshot);
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "getValue:onCancelled:" + databaseError.getMessage());
tcs.setException(databaseError.toException());
}
});
return tcs.getTask();
}
public static <X extends FIRObject> X getValue(final DataSnapshot snapshot, final Class<X> aClass) {
// Log.i(TAG, "getValue");
X firObject = snapshot.getValue(aClass);
firObject.setKey(snapshot.getKey());
return firObject;
}
public static <X extends FIRObject> X getValue(MutableData mutableData, String key, final Class<X> aClass) {
// Log.i(TAG, "getValue");
X firObject = mutableData.getValue(aClass);
if (firObject == null) return null;
firObject.setKey(key);
return firObject;
}
public static <X extends FIRObject> Task<X> getValue(final DatabaseReference ref, final Class<X> aClass) {
Log.d(TAG, "getValue:ref:" + ref.toString());
final TaskCompletionSource<X> tcs = new TaskCompletionSource<>();
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (!dataSnapshot.exists()) {
NullDataException e = new NullDataException(
String.format("%s (%s)", "The value for the path is null.", ref.toString())
);
Log.w(TAG, "getValue:onCancelled:error:" + e.getLocalizedMessage());
tcs.setException(e);
return;
}
X x = dataSnapshot.getValue(aClass);
x.setKey(dataSnapshot.getKey());
tcs.setResult(x);
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "getValue:onCancelled:error:" + databaseError.getMessage());
tcs.setException(databaseError.toException());
}
});
return tcs.getTask();
}
public static Task<DataSnapshot> getValue(final Query query) {
Log.i(TAG, "getValue:ref:" + query.getRef().toString());
final TaskCompletionSource<DataSnapshot> tcs = new TaskCompletionSource<>();
query.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d(TAG, "getValue:onDataChange");
// 어차피 DataSnapshot를 반환하기 때문에 현재 패스의 존재 유무는 사용하는 곳에서 처리하도록 한다.
tcs.setResult(dataSnapshot);
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "getValue:onCancelled", databaseError.toException());
tcs.setException(databaseError.toException());
}
});
return tcs.getTask();
}
public static <X extends FIRObject> Task<X> getValue(final Query query, final Class<X> aClass) {
Log.i(TAG, "getValue:ref:" + query.toString());
final TaskCompletionSource<X> tcs = new TaskCompletionSource<>();
query.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d(TAG, "getValue:onDataChange:dataSnapshot:" + dataSnapshot.getValue());
if (!dataSnapshot.exists()) {
NullDataException e = new NullDataException(
String.format("%s (%s)", "The Value for the path is null.", query.toString())
);
Log.w(TAG, "getValue:onCancelled", e);
tcs.setException(e);
return;
}
tcs.setResult(getValue(dataSnapshot, aClass));
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "getValue:onCancelled", databaseError.toException());
tcs.setException(databaseError.toException());
}
});
return tcs.getTask();
}
public static <X extends FIRObject> Task<X> getChildValue(final Query query, final Class<X> aClass) {
Log.i(TAG, "getValue:ref:" + query.toString());
final TaskCompletionSource<X> tcs = new TaskCompletionSource<>();
query.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d(TAG, "getValue:onDataChange:dataSnapshot:" + dataSnapshot.getValue());
if (!dataSnapshot.exists()) {
NullDataException e = new NullDataException(
String.format("%s (%s)", "The Value for the path is null.", query.toString())
);
Log.w(TAG, "getValue:onCancelled", e);
tcs.setException(e);
return;
}
tcs.setResult(getValue(dataSnapshot.getChildren().iterator().next(), aClass));
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "getValue:onCancelled", databaseError.toException());
tcs.setException(databaseError.toException());
}
});
return tcs.getTask();
}
public static Task<String> getString(final DatabaseReference ref) {
Log.i(TAG, "getString:ref:" + ref.toString());
final TaskCompletionSource<String> tcs = new TaskCompletionSource<>();
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d(TAG, "getString:onDataChange:dataSnapshot:" + dataSnapshot.getValue());
if (!dataSnapshot.exists()) {
NullDataException e = new NullDataException(
String.format("%s (%s)", "The Value for the path is null.", ref.toString())
);
Log.w(TAG, "getString:onCancelled:" + e.getMessage());
tcs.setException(e);
return;
}
tcs.setResult(dataSnapshot.getValue(String.class));
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "getString:onCancelled:" + databaseError.toException().getMessage());
tcs.setException(databaseError.toException());
}
});
return tcs.getTask();
}
public static Task<Boolean> getBoolean(final DatabaseReference ref) {
// Log.i(TAG, "getBoolean:ref:" + ref.toString());
final TaskCompletionSource<Boolean> tcs = new TaskCompletionSource<>();
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Log.d(TAG, "getBoolean:onDataChange:dataSnapshot:" + dataSnapshot.getValue());
if (!dataSnapshot.exists()) {
NullDataException e = new NullDataException(
String.format("%s (%s)", "The Value for the path is null.", ref.toString())
);
Log.w(TAG, "getBoolean:onCancelled:error:" + e.getLocalizedMessage());
tcs.setException(e);
return;
}
tcs.setResult(dataSnapshot.getValue(Boolean.class));
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "getBoolean:onCancelled:error:" + databaseError.getMessage());
tcs.setException(databaseError.toException());
}
});
return tcs.getTask();
}
public static Task<Integer> getInteger(final DatabaseReference ref) {
// Log.i(TAG, "getInteger:ref:" + ref.toString());
final TaskCompletionSource<Integer> tcs = new TaskCompletionSource<>();
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Log.d(TAG, "getInteger:onDataChange:dataSnapshot:" + dataSnapshot.getValue());
if (!dataSnapshot.exists()) {
NullDataException e = new NullDataException(String.format("%s (%s)", "The Value for the path is null.", ref.toString()));
Log.w(TAG, "getInteger:onCancelled:error:" + e.getLocalizedMessage());
tcs.setResult(0);
return;
}
tcs.setResult(dataSnapshot.getValue(Integer.class));
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "getInteger:onCancelled:error:" + databaseError.getMessage());
tcs.setException(databaseError.toException());
}
});
return tcs.getTask();
}
public static Task<Void> runTransaction(DatabaseReference ref, final TransactionHandler handler) {
Log.i(TAG, "runTransaction");
final TaskCompletionSource<Void> tcs = new TaskCompletionSource<>();
ref.runTransaction(new Transaction.Handler() {
final String TAG = "Handler";
@Override
public Transaction.Result doTransaction(MutableData mutableData) {
// 이유는 모르겠지만 최초에 null이 한번 반환되고 두번째에 제대로 된 값이 반환된다.
if (!mutableData.hasChildren()) return Transaction.success(mutableData);
Log.i(TAG, "doTransaction:mutableData:" + mutableData.toString());
return handler.doTransaction(mutableData);
}
@Override
public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot) {
if (!b) {
tcs.setException(databaseError.toException());
}
tcs.setResult(null);
}
});
return tcs.getTask();
}
public static Task<Void> runTransaction(DatabaseReference ref, final Transaction.Handler handler) {
final TaskCompletionSource<Void> tcs = new TaskCompletionSource<>();
ref.runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData mutableData) {
return handler.doTransaction(mutableData);
}
@Override
public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot) {
if (!b) {
tcs.setException(databaseError.toException());
}
tcs.setResult(null);
}
});
return tcs.getTask();
}
public interface TransactionHandler {
Transaction.Result doTransaction(MutableData mutableData);
}
public static Task<Void> removeValue(DatabaseReference ref) {
Log.i(TAG, "removeValue");
final TaskCompletionSource<Void> tcs = new TaskCompletionSource<>();
ref.removeValue((databaseError, databaseReference) -> {
if (databaseError != null) {
Log.w(TAG, "removeValue:ERROR:" + databaseError.getMessage());
tcs.setException(databaseError.toException());
}
Log.d(TAG, "removeValue:SUCCESS");
tcs.setResult(null);
});
return tcs.getTask();
}
public static String getPath(DatabaseReference ref) {
StringBuilder path = new StringBuilder("/" + ref.getKey());
while (ref.getParent().getKey() != null) {
ref = ref.getParent();
path.insert(0, "/" + ref.getKey());
}
return path.toString();
}
public static String getPath(DatabaseReference ref, String lastKey) {
return String.format("%s/%s", getPath(ref), lastKey);
}
public static boolean isLastDataReached(DataSnapshot snapshot, int requestedAmount) {
int count = (int) snapshot.getChildrenCount();
boolean isReached = count < requestedAmount;
Log.d(TAG, "isLastDataReached:count:" + count + "|requestedLimit:" + requestedAmount + "|result:" + isReached);
return isReached;
}
public static class NullDataException extends DatabaseException {
@SuppressLint("RestrictedApi")
public NullDataException(String detailMessage) {
super(detailMessage);
}
}
}
package app.pwdr.firebase.model;
import androidx.annotation.Nullable;
import com.google.firebase.database.Exclude;
import com.google.firebase.database.IgnoreExtraProperties;
import java.io.Serializable;
@IgnoreExtraProperties
public class FIRObject implements Serializable {
@Exclude
@Nullable
String key;
@Exclude
@Nullable
public String getKey() {
return key;
}
@Exclude
public void setKey(@Nullable String key) {
this.key = key;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment