Отказ от ответственности : поскольку этот вопрос относится к моей работе, я не могу вникнуть в реальные детали. Я постараюсь предоставить как можно больше информации о проблеме. Кроме того, я новичок в ReactNative. Просто начал использовать его с недели, и я мог бы спросить кое-что чрезвычайно тривиальное.
Фон
Есть два приложения, назовем их App-A и App-B. В приложении A есть условия для запуска действий или получения какой-либо информации из приложения B. При запросе некоторой информации контракт на установление связи устанавливается так, что App-A будет startActivityForResult
. Намерение будет явно ссылаться на действие App-B (безголовое действие; нет пользовательского интерфейса; каждая операция обрабатывается в фоновом режиме). App-B должен (в идеале) поместить запрос в свои внутренние службы, получить ответ и setResult(...)
для действия перед вызовом finish()
. У меня пока не работает последняя часть (суть проблемы, обсуждаемой ниже)
Структура App-B
App-B использует ReactNative для большинства вещей на стороне клиента. Все вызовы сетевого API, выполняемые App-B, выполняются в коде JavaScript. Когда App-A размещает запрос «search», он передает «searchTerm», который App-B должен отправить своим внутренним службам, чтобы получить результаты / ответ. Как только ответ получен, его необходимо отправить обратно в App-A, «установив результат», используя setResult(…)
в контексте действия.
Задача
Проблема заключается в передаче ответа / результатов из кода JavaScript в собственный код в App-B. Поскольку мне нужно «поддерживать запрос» в активности App-B, мне нужно «подождать», пока результаты не станут доступны, прежде чем устанавливать результат для потребления App-A (setResult(...)
).
Вот то, что я пробовал до сих пор
- Используйте EventEmitters : При этом код Java в App-B будет генерировать событие с идентификатором для кода ReactNative JavaScript. Однако метод
emit(…)
принимает только два параметра - «имя-события / идентификатор-события» и объект. Объект может быть примитивным типом данных, Callback или WritableArray / WritableMap (коллекции, определенные в платформе ReactNative). Поскольку мне нужно передать вышеупомянутый «searchTerm» в код JavaScript для размещения сетевого запроса, я не могу передать объект Callback. Если я отправляю объект обратного вызова, то я не могу отправить «searchTerm», поскольку могу передать только один параметр. Я не думаю, что Promise
работает здесь, так как я все еще не смогу отправить "searchTerm"
// The "emit" method call below only takes 2 arguments. I can only pass
// either the "searchTerm" or a "Callback"
reactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)(eventName, someObject);
- Определить JavaScriptModule : Определение и предоставление «JavaScriptModule» - это способ, которым нативный / Java-код может вызывать метод, определенный в коде JavaScript. Этот метод может быть определен так, чтобы принимать столько параметров / аргументов, сколько необходимо. Идея заключалась в том, чтобы вызвать метод JavaScript из нативного кода и передать как searchTerm, так и объект обратного вызова. Однако, когда переданные аргументы проверяются, создается исключение RuntimeException, поскольку JavaScriptModules могут передавать только аргументы типа примитива или объекты «WritableMap / Array».
Callback
Объекты не поддерживаются. То же самое с Promise
объектами; они не являются поддерживаемыми типами аргументов.
// Defined a SearchModule like so (required Module registration is done using ReactPackage
// and setting it in the setPackages() method)
// Followed this: https://stackoverflow.com/questions/38661060/are-there-any-guides-for-implementing-javascriptmodule-in-react-native
// Unfortunately, this throws a RuntimeException since "Callback" is not a
// supported argument
public interface MySearchModule extends JavaScriptModule {
void call(String eventType, String searchQuery, Callback callback);
}
/**
* Different file below
*/
// Arguments.java code snippet in the RN framework
for(int i = 0; i < args.length; ++i) {
Object argument = args[i];
if (argument == null) {
arguments.pushNull();
} else {
Class argumentClass = argument.getClass();
if (argumentClass == Boolean.class) {
arguments.pushBoolean((Boolean)argument);
} else if (argumentClass == Integer.class) {
arguments.pushDouble(((Integer)argument).doubleValue());
} else if (argumentClass == Double.class) {
arguments.pushDouble((Double)argument);
} else if (argumentClass == Float.class) {
arguments.pushDouble(((Float)argument).doubleValue());
} else if (argumentClass == String.class) {
arguments.pushString(argument.toString());
} else if (argumentClass == WritableNativeMap.class) {
arguments.pushMap((WritableNativeMap)argument);
} else {
if (argumentClass != WritableNativeArray.class) {
throw new RuntimeException("Cannot convert argument of type " + argumentClass);
}
arguments.pushArray((WritableNativeArray)argument);
}
}
}
У меня есть вопросы
- Возможно ли достичь чего-то подобного в среде ReactNative, где код Java (деятельность) может вызывать код JavaScript, передавая набор параметров и получая ответ обратно?
- Есть ли что-то в отношении EventEmitters / JavaScriptModule, с помощью которого я мог бы добиться требуемого результата?
- Есть ли какой-либо другой метод для обмена данными через Native / JavaScript, кроме EventEmitters / JavaScriptModule?
- Есть ли другие возможности для этого варианта использования?