-
Notifications
You must be signed in to change notification settings - Fork 24.4k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
[Android] Expose ArgumentExtractor to BaseJavaModule subclasses #9931
Conversation
By analyzing the blame information on this pull request, we identified @bestander and @astreet to be potential reviewers. |
@felipecsl updated the pull request - view changes |
Maybe an instrumentation test would be required |
@felipecsl updated the pull request - view changes |
@felipecsl updated the pull request - view changes |
1 similar comment
@felipecsl updated the pull request - view changes |
alright test added, @bestander PTAL |
I'll send a note to android people. |
friendly ping again 😄 |
@felipecsl updated the pull request - view changes |
I kinda like this idea but it's a change of how we see the bridge if it can send complex objects, however as you noted we already do this today just not in a graceful way. Do you have plans to support this on iOS too? |
static final public String METHOD_TYPE_ASYNC = "async"; | ||
static final public String METHOD_TYPE_PROMISE= "promise"; | ||
private static final String METHOD_TYPE_ASYNC = "async"; | ||
private static final String METHOD_TYPE_PROMISE= "promise"; | ||
static final public String METHOD_TYPE_SYNC = "sync"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you change this one too? or at least move the public to be at the beginning
* to {@link ReactMethod} annotated methods with the given {@code Type}. Return {@code null} if | ||
* this factory can't handle the provided type. | ||
*/ | ||
public interface Factory { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you use a factory instead of just having a list of ArgumentExtractor
s?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This allows you to "plug-in" the logic that associates a specific ArgumentExtractor
with a Type
. This way you wouldn't need the big if/else/else if...
chain in buildArgumentExtractors()
and could delegate it to the Factories to provide or not an extractor for the provided Type.
|
||
private static abstract class ArgumentExtractor<T> { | ||
public BaseJavaModule(List<? extends ArgumentExtractor.Factory> argumentExtractorFactories) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'd prefer having this be provided with from a method instead?
Like: List<ArgumentExtractor> getCustomExtractors()
Also define an extra class so we can tell the type from the extractor, something like:
abstract class CustomArgumentExtractor<T> extends ArgumentExtractor {
Class<T> getSupportedType();
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I though about doing this way but I'm really not a fan of having this "inheritance party" behavior. Using constructor arguments is a much more explicit way of letting subclasses know about that functionality and having a hook point for defining that.
I understand if you're not a fan of that style though and I'd be happy to change it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's go ahead and change to using the method instead. I realize I feel strongly about this for a few reasons; even if I agree on that inheritance is not always a good solution, however in this case it's really implementing an interface (even if we provide a simplifying base class). The method also gives us more lazy behavior which is something were trying hard to move to, it also matches how this class already works.
@felipecsl updated the pull request - view changes |
I can look into making this change for iOS too! |
I'm ok with this change, @javache are you ok with something similar on iOS? Nits: we haven't been adding |
It's been a while since the last commit was reviewed and the labels show this pull request needs review. Based on the blame information for the files in this pull request we identified @bestander as a potential reviewer. Could you take a look please or cc someone with more context? |
BTW I don't think I'll have time to make these changes on iOS as well, at least not for now |
@lexs any further comments? @felipecsl there's some conflicts that need to be addressed in |
Added a comment about using a method instead of inheritance, rebase, and I'll happily merge it (or somebody else can go ahead and do it). |
@lexs ok thanks for your review, I'll rebase it and update later tonight |
Sorry for the delay -- seems reasonable to me! @facebook-github-bot shipit |
@astreet has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator. |
I tried to merge this pull request into the Facebook internal repo but some checks failed. To unblock yourself please check the following: Does this pull request pass all open source tests on GitHub? If not please fix those. Does the code still apply cleanly on top of GitHub master? If not can please rebase. In all other cases this means some internal test failed, for example a part of a fb app won't work with this pull request. I've added the Import Failed label to this pull request so it is easy for someone at fb to find the pull request and check what failed. If you don't see anyone comment in a few days feel free to comment mentioning one of the core contributors to the project so they get a notification. |
@@ -299,9 +305,28 @@ public void testGetTypeFromArray() { | |||
assertEquals(ReadableType.Null, array.getType(6)); | |||
} | |||
|
|||
public void testCustomTypeViaArgumentExtractor() { | |||
mCatalystInstance.getJSModule(TestJSToJavaParametersModule.class).returnCustomType(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Land failed as tests don't compile since TestJSToJavaParametersModule#returnCustomType
isn't defined. Make sure to run the integration tests first: ./scripts/run-android-local-integration-tests.sh
Ping @felipecsl |
Closing this because of no response for two weeks. But it was accepted, just needs some minor tweaks and rebase. @felipecsl feel free to send a new PR mentioning this one so people know it should be merged. |
Summary
This change allows subclasses of
BaseJavaModule
to provide a list ofArgumentExtractor
factories.ArgumentExtractor.Factory
is a new interface that allows returning a customArgumentExtractor
for a given type. By doing this, we allow@ReactMethod
annotated methods to take arguments of arbitrary types (not just primitives,ReadableMap
andReadableArray
).Motivation
For any non-trivial use of java modules, you'll quickly need to start sending complex objects through the bridge and it becomes very cumbersome and error prone to manually parse them out of a
ReadableMap
orReadableArray
every time.This allows for more flexibility and more powerful java modules with little overhead.
Test Plan
I'm still working on the unit test for this, but opening the PR for early feedback.