Android: Added support to arrays in toBundle

Summary:
The support for `ReadableArray` in `toBundle` was never implemented, throwing an `UnsupportedOperationException` when trying to convert an array.

* Created `toList` -- A method that converts a `ReadableArray` to an `ArrayList`
* Modified `toBundle` to support arrays using `toList`
* Created `fromList` -- A method that converts a `List` to a `WritableArray`
* Modified `fromBundle` to also support lists using `fromList`

This PR allows `toBundle` and `fromBundle` (as well as `toList` and `fromList`) to work consistently without loosing information.

**Test Plan**

I've created three different arrays: one full of integers, one full of strings, and one mixed (with a integer, a boolean, a string, null, a map with a string and a boolean array), putting all of them inside a map.

After converting the map to a `Bundle` using `toBundle`, the integer array was retrieved through `Bundle.getIntegerArrayList`, the string array through `Bundle.getStringArrayList` and the mixed array through `Bundle.get` (casting it to an `ArrayList`)

After checking whether each value from the bundle was correct, I converted the bundle back to a map using `fromBundle`, and checked again every value.

The code and results from the test can be found in [this gist](https://gist.github.com/Guichaguri/5c7574b31f9584b6a9a0c182fd940a86).
Closes https://github.com/facebook/react-native/pull/15056

Differential Revision: D5460966

Pulled By: javache

fbshipit-source-id: a11b450eae4186e68bed7b8ce7dea8e5982e689a
This commit is contained in:
Guichaguri 2017-07-20 02:37:42 -07:00 committed by Facebook Github Bot
parent 3ce36698de
commit bc0717c6cc

View File

@ -11,6 +11,7 @@ package com.facebook.react.bridge;
import java.lang.reflect.Array;
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@ -235,6 +236,40 @@ public class Arguments {
return catalystArray;
}
/**
* Convert a {@link List} to a {@link WritableArray}.
*
* @param list the list to convert. Supported value types are: {@code null}, {@code String}, {@code Bundle},
* {@code List}, {@code Number}, {@code Boolean}, and all array types supported in {@link #fromArray(Object)}.
* @return the converted {@link WritableArray}
* @throws IllegalArgumentException if one of the values from the passed list is none of the above types
*/
public static WritableArray fromList(List list) {
WritableArray catalystArray = createArray();
for (Object obj : list) {
if (obj == null) {
catalystArray.pushNull();
} else if (obj.getClass().isArray()) {
catalystArray.pushArray(fromArray(obj));
} else if (obj instanceof Bundle) {
catalystArray.pushMap(fromBundle((Bundle) obj));
} else if (obj instanceof List) {
catalystArray.pushArray(fromList((List) obj));
} else if (obj instanceof String) {
catalystArray.pushString((String) obj);
} else if (obj instanceof Integer) {
catalystArray.pushInt((Integer) obj);
} else if (obj instanceof Number) {
catalystArray.pushDouble(((Number) obj).doubleValue());
} else if (obj instanceof Boolean) {
catalystArray.pushBoolean((Boolean) obj);
} else {
throw new IllegalArgumentException("Unknown value type " + obj.getClass());
}
}
return catalystArray;
}
/**
* Convert a {@link Bundle} to a {@link WritableMap}. Supported key types in the bundle
* are:
@ -242,6 +277,7 @@ public class Arguments {
* <ul>
* <li>primitive types: int, float, double, boolean</li>
* <li>arrays supported by {@link #fromArray(Object)}</li>
* <li>lists supported by {@link #fromList(List)}</li>
* <li>{@link Bundle} objects that are recursively converted to maps</li>
* </ul>
*
@ -269,6 +305,8 @@ public class Arguments {
map.putBoolean(key, (Boolean) value);
} else if (value instanceof Bundle) {
map.putMap(key, fromBundle((Bundle) value));
} else if (value instanceof List) {
map.putArray(key, fromList((List) value));
} else {
throw new IllegalArgumentException("Could not convert " + value.getClass());
}
@ -276,8 +314,58 @@ public class Arguments {
return map;
}
/**
* Convert a {@link WritableArray} to a {@link ArrayList}.
*
* @param readableArray the {@link WritableArray} to convert.
* @return the converted {@link ArrayList}.
*/
@Nullable
public static ArrayList toList(@Nullable ReadableArray readableArray) {
if (readableArray == null) {
return null;
}
ArrayList list = new ArrayList();
for (int i = 0; i < readableArray.size(); i++) {
switch (readableArray.getType(i)) {
case Null:
list.add(null);
break;
case Boolean:
list.add(readableArray.getBoolean(i));
break;
case Number:
double number = readableArray.getDouble(i);
if (number == Math.rint(number)) {
// Add as an integer
list.add((int) number);
} else {
// Add as a double
list.add(number);
}
break;
case String:
list.add(readableArray.getString(i));
break;
case Map:
list.add(toBundle(readableArray.getMap(i)));
break;
case Array:
list.add(toList(readableArray.getArray(i)));
break;
default:
throw new IllegalArgumentException("Could not convert object in array.");
}
}
return list;
}
/**
* Convert a {@link WritableMap} to a {@link Bundle}.
* Note: Each array is converted to an {@link ArrayList}.
*
* @param readableMap the {@link WritableMap} to convert.
* @return the converted {@link Bundle}.
@ -312,8 +400,8 @@ public class Arguments {
bundle.putBundle(key, toBundle(readableMap.getMap(key)));
break;
case Array:
// TODO t8873322
throw new UnsupportedOperationException("Arrays aren't supported yet.");
bundle.putSerializable(key, toList(readableMap.getArray(key)));
break;
default:
throw new IllegalArgumentException("Could not convert object with key: " + key + ".");
}