[android][database] implement DataSnapshotToMapAsyncTask to address performance issue - #1284
This commit is contained in:
parent
66aa5ccb67
commit
26338d8d62
|
@ -3,8 +3,12 @@ package io.invertase.firebase.database;
|
|||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
import android.util.Log;
|
||||
import android.os.AsyncTask;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.facebook.react.bridge.Promise;
|
||||
|
@ -33,6 +37,46 @@ class RNFirebaseDatabaseReference {
|
|||
private HashMap<String, ChildEventListener> childEventListeners = new HashMap<>();
|
||||
private HashMap<String, ValueEventListener> valueEventListeners = new HashMap<>();
|
||||
|
||||
/**
|
||||
* AsyncTask to convert DataSnapshot instances to WritableMap instances.
|
||||
*
|
||||
* Introduced due to https://github.com/invertase/react-native-firebase/issues/1284
|
||||
*/
|
||||
private static class DataSnapshotToMapAsyncTask extends AsyncTask<Object, Void, WritableMap> {
|
||||
|
||||
private WeakReference<ReactContext> reactContextWeakReference;
|
||||
private WeakReference<RNFirebaseDatabaseReference> referenceWeakReference;
|
||||
|
||||
DataSnapshotToMapAsyncTask(ReactContext context, RNFirebaseDatabaseReference reference) {
|
||||
referenceWeakReference = new WeakReference<>(reference);
|
||||
reactContextWeakReference = new WeakReference<>(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final WritableMap doInBackground(Object... params) {
|
||||
DataSnapshot dataSnapshot = (DataSnapshot) params[0];
|
||||
@Nullable String previousChildName = (String) params[1];
|
||||
|
||||
try {
|
||||
return RNFirebaseDatabaseUtils.snapshotToMap(dataSnapshot, previousChildName);
|
||||
} catch (RuntimeException e) {
|
||||
if (isAvailable()) {
|
||||
reactContextWeakReference.get().handleException(e);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(WritableMap writableMap) {
|
||||
// do nothing as overridden on usage
|
||||
}
|
||||
|
||||
Boolean isAvailable() {
|
||||
return reactContextWeakReference.get() != null && referenceWeakReference.get() != null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RNFirebase wrapper around FirebaseDatabaseReference,
|
||||
* handles Query generation and event listeners.
|
||||
|
@ -130,15 +174,22 @@ class RNFirebaseDatabaseReference {
|
|||
* @param promise
|
||||
*/
|
||||
private void addOnceValueEventListener(final Promise promise) {
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
final DataSnapshotToMapAsyncTask asyncTask = new DataSnapshotToMapAsyncTask(reactContext, this) {
|
||||
@Override
|
||||
protected void onPostExecute(WritableMap writableMap) {
|
||||
if (this.isAvailable()) promise.resolve(writableMap);
|
||||
}
|
||||
};
|
||||
|
||||
ValueEventListener onceValueEventListener = new ValueEventListener() {
|
||||
@Override
|
||||
public void onDataChange(DataSnapshot dataSnapshot) {
|
||||
WritableMap data = RNFirebaseDatabaseUtils.snapshotToMap(dataSnapshot, null);
|
||||
promise.resolve(data);
|
||||
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
|
||||
asyncTask.execute(dataSnapshot, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(DatabaseError error) {
|
||||
public void onCancelled(@NonNull DatabaseError error) {
|
||||
RNFirebaseDatabase.handlePromise(promise, error);
|
||||
}
|
||||
};
|
||||
|
@ -156,7 +207,7 @@ class RNFirebaseDatabaseReference {
|
|||
private void addChildOnceEventListener(final String eventName, final Promise promise) {
|
||||
ChildEventListener childEventListener = new ChildEventListener() {
|
||||
@Override
|
||||
public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
|
||||
public void onChildAdded(@NonNull DataSnapshot dataSnapshot, String previousChildName) {
|
||||
if ("child_added".equals(eventName)) {
|
||||
query.removeEventListener(this);
|
||||
WritableMap data = RNFirebaseDatabaseUtils.snapshotToMap(dataSnapshot, previousChildName);
|
||||
|
@ -165,7 +216,7 @@ class RNFirebaseDatabaseReference {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) {
|
||||
public void onChildChanged(@NonNull DataSnapshot dataSnapshot, String previousChildName) {
|
||||
if ("child_changed".equals(eventName)) {
|
||||
query.removeEventListener(this);
|
||||
WritableMap data = RNFirebaseDatabaseUtils.snapshotToMap(dataSnapshot, previousChildName);
|
||||
|
@ -174,7 +225,7 @@ class RNFirebaseDatabaseReference {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onChildRemoved(DataSnapshot dataSnapshot) {
|
||||
public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
|
||||
if ("child_removed".equals(eventName)) {
|
||||
query.removeEventListener(this);
|
||||
WritableMap data = RNFirebaseDatabaseUtils.snapshotToMap(dataSnapshot, null);
|
||||
|
@ -183,7 +234,7 @@ class RNFirebaseDatabaseReference {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {
|
||||
public void onChildMoved(@NonNull DataSnapshot dataSnapshot, String previousChildName) {
|
||||
if ("child_moved".equals(eventName)) {
|
||||
query.removeEventListener(this);
|
||||
WritableMap data = RNFirebaseDatabaseUtils.snapshotToMap(dataSnapshot, previousChildName);
|
||||
|
@ -192,7 +243,7 @@ class RNFirebaseDatabaseReference {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(DatabaseError error) {
|
||||
public void onCancelled(@NonNull DatabaseError error) {
|
||||
query.removeEventListener(this);
|
||||
RNFirebaseDatabase.handlePromise(promise, error);
|
||||
}
|
||||
|
@ -243,35 +294,35 @@ class RNFirebaseDatabaseReference {
|
|||
if (!hasEventListener(eventRegistrationKey)) {
|
||||
ChildEventListener childEventListener = new ChildEventListener() {
|
||||
@Override
|
||||
public void onChildAdded(DataSnapshot dataSnapshot, String previousChildName) {
|
||||
public void onChildAdded(@NonNull DataSnapshot dataSnapshot, String previousChildName) {
|
||||
if ("child_added".equals(eventType)) {
|
||||
handleDatabaseEvent("child_added", registration, dataSnapshot, previousChildName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChildChanged(DataSnapshot dataSnapshot, String previousChildName) {
|
||||
public void onChildChanged(@NonNull DataSnapshot dataSnapshot, String previousChildName) {
|
||||
if ("child_changed".equals(eventType)) {
|
||||
handleDatabaseEvent("child_changed", registration, dataSnapshot, previousChildName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChildRemoved(DataSnapshot dataSnapshot) {
|
||||
public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {
|
||||
if ("child_removed".equals(eventType)) {
|
||||
handleDatabaseEvent("child_removed", registration, dataSnapshot, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChildMoved(DataSnapshot dataSnapshot, String previousChildName) {
|
||||
public void onChildMoved(@NonNull DataSnapshot dataSnapshot, String previousChildName) {
|
||||
if ("child_moved".equals(eventType)) {
|
||||
handleDatabaseEvent("child_moved", registration, dataSnapshot, previousChildName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(DatabaseError error) {
|
||||
public void onCancelled(@NonNull DatabaseError error) {
|
||||
removeEventListener(eventRegistrationKey);
|
||||
handleDatabaseError(registration, error);
|
||||
}
|
||||
|
@ -292,12 +343,12 @@ class RNFirebaseDatabaseReference {
|
|||
if (!hasEventListener(eventRegistrationKey)) {
|
||||
ValueEventListener valueEventListener = new ValueEventListener() {
|
||||
@Override
|
||||
public void onDataChange(DataSnapshot dataSnapshot) {
|
||||
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
|
||||
handleDatabaseEvent("value", registration, dataSnapshot, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(DatabaseError error) {
|
||||
public void onCancelled(@NonNull DatabaseError error) {
|
||||
removeEventListener(eventRegistrationKey);
|
||||
handleDatabaseError(registration, error);
|
||||
}
|
||||
|
@ -314,16 +365,23 @@ class RNFirebaseDatabaseReference {
|
|||
* @param dataSnapshot
|
||||
* @param previousChildName
|
||||
*/
|
||||
private void handleDatabaseEvent(String eventType, ReadableMap registration, DataSnapshot dataSnapshot, @Nullable String previousChildName) {
|
||||
WritableMap event = Arguments.createMap();
|
||||
WritableMap data = RNFirebaseDatabaseUtils.snapshotToMap(dataSnapshot, previousChildName);
|
||||
private void handleDatabaseEvent(final String eventType, final ReadableMap registration, DataSnapshot dataSnapshot, @Nullable String previousChildName) {
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
DataSnapshotToMapAsyncTask asyncTask = new DataSnapshotToMapAsyncTask(reactContext, this) {
|
||||
@Override
|
||||
protected void onPostExecute(WritableMap data) {
|
||||
if (this.isAvailable()) {
|
||||
WritableMap event = Arguments.createMap();
|
||||
event.putMap("data", data);
|
||||
event.putString("key", key);
|
||||
event.putString("eventType", eventType);
|
||||
event.putMap("registration", Utils.readableMapToWritableMap(registration));
|
||||
Utils.sendEvent(reactContext, "database_sync_event", event);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
event.putMap("data", data);
|
||||
event.putString("key", key);
|
||||
event.putString("eventType", eventType);
|
||||
event.putMap("registration", Utils.readableMapToWritableMap(registration));
|
||||
|
||||
Utils.sendEvent(reactContext, "database_sync_event", event);
|
||||
asyncTask.execute(dataSnapshot, previousChildName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue