From 3306d92f2d4712a05489d116f423949d591e8d7a Mon Sep 17 00:00:00 2001 From: Salakar Date: Sun, 6 May 2018 00:51:54 +0100 Subject: [PATCH] [android][utils] refactor legacy utils to use react natives own conversion utilities for performance --- .../java/io/invertase/firebase/Utils.java | 230 +++++++----------- .../firestore/FirestoreSerialize.java | 5 - 2 files changed, 83 insertions(+), 152 deletions(-) diff --git a/android/src/main/java/io/invertase/firebase/Utils.java b/android/src/main/java/io/invertase/firebase/Utils.java index 5921d146..fdbcce17 100644 --- a/android/src/main/java/io/invertase/firebase/Utils.java +++ b/android/src/main/java/io/invertase/firebase/Utils.java @@ -4,37 +4,24 @@ import android.app.ActivityManager; import android.content.Context; import android.util.Log; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReactContext; import com.facebook.react.modules.core.DeviceEventManagerModule; -import com.facebook.react.bridge.ReadableType; import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMapKeySetIterator; + +import javax.annotation.Nullable; @SuppressWarnings("WeakerAccess") public class Utils { private static final String TAG = "Utils"; - // TODO NOTE - public static void todoNote(final String tag, final String name, final Callback callback) { - Log.e(tag, "The method " + name + " has not yet been implemented."); - Log.e(tag, "Feel free to contribute to finish the method in the source."); - - WritableMap errorMap = Arguments.createMap(); - errorMap.putString("error", "unimplemented"); - callback.invoke(null, errorMap); - } - /** * send a JS event **/ @@ -49,162 +36,111 @@ public class Utils { } /** - * @param key map key - * @param value map value - * @param map map + * Takes a value and calls the appropriate setter for its type on the target map + key + * + * @param key String key to set on target map + * @param value Object value to set on target map + * @param map WritableMap target map to write the value to */ - public static void mapPutValue(String key, Object value, WritableMap map) { - String type = value != null ? value.getClass().getName() : ""; - switch (type) { - case "java.lang.Boolean": - map.putBoolean(key, (Boolean) value); - break; - case "java.lang.Long": - Long longVal = (Long) value; - map.putDouble(key, (double) longVal); - break; - case "java.lang.Float": - float floatVal = (float) value; - map.putDouble(key, (double) floatVal); - break; - case "java.lang.Double": - map.putDouble(key, (Double) value); - break; - case "java.lang.String": - map.putString(key, (String) value); - break; - default: - map.putNull(key); + @SuppressWarnings("unchecked") + public static void mapPutValue(String key, @Nullable Object value, WritableMap map) { + if (value == null) { + map.putNull(key); + } else { + String type = value.getClass().getName(); + switch (type) { + case "java.lang.Boolean": + map.putBoolean(key, (Boolean) value); + break; + case "java.lang.Long": + Long longVal = (Long) value; + map.putDouble(key, (double) longVal); + break; + case "java.lang.Float": + float floatVal = (float) value; + map.putDouble(key, (double) floatVal); + break; + case "java.lang.Double": + map.putDouble(key, (Double) value); + break; + case "java.lang.String": + map.putString(key, (String) value); + break; + default: + if (List.class.isAssignableFrom(value.getClass())) { + map.putArray(key, Arguments.makeNativeArray((List) value)); + } else if (Map.class.isAssignableFrom(value.getClass())) { + map.putMap(key, Arguments.makeNativeMap((Map) value)); + } else { + Log.d(TAG, "utils:mapPutValue:unknownType:" + type); + map.putNull(key); + } + } } } - /** - * @param map - * @return + * Convert a ReadableMap to a WritableMap for the purposes of re-sending back to JS + * TODO This is now a legacy util - internally uses RN functionality + * + * @param map ReadableMap + * @return WritableMap */ public static WritableMap readableMapToWritableMap(ReadableMap map) { WritableMap writableMap = Arguments.createMap(); - - ReadableMapKeySetIterator iterator = map.keySetIterator(); - while (iterator.hasNextKey()) { - String key = iterator.nextKey(); - ReadableType type = map.getType(key); - switch (type) { - case Null: - writableMap.putNull(key); - break; - case Boolean: - writableMap.putBoolean(key, map.getBoolean(key)); - break; - case Number: - writableMap.putDouble(key, map.getDouble(key)); - break; - case String: - writableMap.putString(key, map.getString(key)); - break; - case Map: - writableMap.putMap(key, readableMapToWritableMap(map.getMap(key))); - break; - case Array: - // TODO writableMap.putArray(key, readableArrayToWritableArray(map.getArray(key))); - break; - default: - throw new IllegalArgumentException("Could not convert object with key: " + key + "."); - } - - } - + // https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/bridge/WritableNativeMap.java#L54 + writableMap.merge(map); return writableMap; } - + /** + * Convert a ReadableMap into a native Java Map + * TODO This is now a legacy util - internally uses RN functionality + * + * @param readableMap ReadableMap + * @return Map + */ public static Map recursivelyDeconstructReadableMap(ReadableMap readableMap) { - Map deconstructedMap = new HashMap<>(); - if (readableMap == null) { - return deconstructedMap; - } - - ReadableMapKeySetIterator iterator = readableMap.keySetIterator(); - while (iterator.hasNextKey()) { - String key = iterator.nextKey(); - ReadableType type = readableMap.getType(key); - switch (type) { - case Null: - deconstructedMap.put(key, null); - break; - case Boolean: - deconstructedMap.put(key, readableMap.getBoolean(key)); - break; - case Number: - deconstructedMap.put(key, readableMap.getDouble(key)); - break; - case String: - deconstructedMap.put(key, readableMap.getString(key)); - break; - case Map: - deconstructedMap.put(key, Utils.recursivelyDeconstructReadableMap(readableMap.getMap(key))); - break; - case Array: - deconstructedMap.put(key, Utils.recursivelyDeconstructReadableArray(readableMap.getArray(key))); - break; - default: - throw new IllegalArgumentException("Could not convert object with key: " + key + "."); - } - - } - return deconstructedMap; + // https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeMap.java#L216 + return readableMap.toHashMap(); } + /** + * Convert a ReadableArray into a native Java Map + * TODO This is now a legacy util - internally uses RN functionality + * + * @param readableArray ReadableArray + * @return List + */ public static List recursivelyDeconstructReadableArray(ReadableArray readableArray) { - List deconstructedList = new ArrayList<>(readableArray.size()); - for (int i = 0; i < readableArray.size(); i++) { - ReadableType indexType = readableArray.getType(i); - switch (indexType) { - case Null: - deconstructedList.add(i, null); - break; - case Boolean: - deconstructedList.add(i, readableArray.getBoolean(i)); - break; - case Number: - deconstructedList.add(i, readableArray.getDouble(i)); - break; - case String: - deconstructedList.add(i, readableArray.getString(i)); - break; - case Map: - deconstructedList.add(i, Utils.recursivelyDeconstructReadableMap(readableArray.getMap(i))); - break; - case Array: - deconstructedList.add(i, Utils.recursivelyDeconstructReadableArray(readableArray.getArray(i))); - break; - default: - throw new IllegalArgumentException("Could not convert object at index " + i + "."); - } - } - return deconstructedList; + // https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/bridge/ReadableNativeArray.java#L175 + return readableArray.toArrayList(); } + /** + * We need to check if app is in foreground otherwise the app will crash. + * http://stackoverflow.com/questions/8489993/check-android-application-is-in-foreground-or-not + * + * @param context Context + * @return boolean + */ public static boolean isAppInForeground(Context context) { - /** - We need to check if app is in foreground otherwise the app will crash. - http://stackoverflow.com/questions/8489993/check-android-application-is-in-foreground-or-not - **/ ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); - List appProcesses = - activityManager.getRunningAppProcesses(); - if (appProcesses == null) { - return false; - } + if (activityManager == null) return false; + + List appProcesses = activityManager.getRunningAppProcesses(); + if (appProcesses == null) return false; + final String packageName = context.getPackageName(); for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) { - if (appProcess.importance == - ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && - appProcess.processName.equals(packageName)) { + if ( + appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND + && appProcess.processName.equals(packageName) + ) { return true; } } + return false; } } diff --git a/android/src/main/java/io/invertase/firebase/firestore/FirestoreSerialize.java b/android/src/main/java/io/invertase/firebase/firestore/FirestoreSerialize.java index d35e44d5..6a5bb196 100644 --- a/android/src/main/java/io/invertase/firebase/firestore/FirestoreSerialize.java +++ b/android/src/main/java/io/invertase/firebase/firestore/FirestoreSerialize.java @@ -6,7 +6,6 @@ import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableMapKeySetIterator; -import com.facebook.react.bridge.ReadableType; import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; import com.google.firebase.firestore.DocumentChange; @@ -18,15 +17,11 @@ import com.google.firebase.firestore.FirebaseFirestore; import com.google.firebase.firestore.GeoPoint; import com.google.firebase.firestore.QuerySnapshot; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.TimeZone; import io.invertase.firebase.Utils;